Как добавить поле ForeignKey для сохранения в ModelForm Django?

При создании своего сайта я столкнулся со следующей проблемой: пользователь может добавить статью, и поэтому модель статьи имеет поле ForeignKey - author.

Я создал форму для его добавления, унаследовав ее от ModelForm, так как мне кажется, что так будет логичнее (ведь она взаимодействует напрямую с db). Проблема в том, что я не могу добавить это поле в форму, так как его нельзя заполнить, оно должно быть взято из самого запроса.

author = request.user.pk

Как сделать так, чтобы форма сохраняла и id автора? Без этого возникает ошибка: NOT NULL CONSTRAINT FAILED, что логично, так как форма не сохраняет пк и поэтому он равен null; но FOREIGN KEY не может быть null.

Единственный способ - наследовать его от класса Form? Я не очень хочу этого делать... Я думал о "переопределении" метода save() так, чтобы у него был еще один аргумент - id автора:

form.save(author=request.user.pk)

Таким образом это будет работать. Но я передумал, потому что если что-то пойдет не так, это испортит всю базу данных... Метод save() слишком глобальный. Более того, вполне может существовать другой способ решения моей проблемы, более эффективный и понятный.

Вот код для моей формы:

class ArticleForm(ModelForm):
    class Meta:
        model = Article
        fields = ['title', 'content']
        widgets = {'title' : TextInput(attrs={'class' : 'create_article_title', 
                                              'placeholder' : 'Enter the heading...' }),
                   'content' : Textarea(attrs={'class' : 'create_article_content', 
                                               'placeholder' : 'Your article...' })}

и моя модель:

class Article(Model):
    title        = CharField(max_length=30)
    content      = CharField(max_length=5000)
    author       = ForeignKey(User, on_delete=CASCADE)
    rating       = IntegerField(default=0)
    created      = DateField(auto_now_add=True)
    last_updated = DateField(auto_now_add=True)

    articles = ArticleManager()
    objects = Manager()

и мое мнение:

class AddArticle(View):
    template_name = 'myapp/addarticle.html'

    def get(self, request):
        context = {'add_article_form' : ArticleForm()}
        return render(request, self.template_name, context=context)

    def post(self, request):
        form = ArticleForm()
        form.save()
        return redirect('index')

Похоже, я совершенно не понимаю основ создания ModelForm...

Я полагаю, что вы хотите использовать FormView и сделать что-то вроде этого:

class AddArticle(LoginRequiredMixin, FormView):
    form_class = ArticleForm
    template_name = 'myapp/addarticle.html'
    success_url = 'index'

    def get(self, request, *args, **kwargs):
        context = {'add_article_form' : ArticleForm()}
        return render(request, self.template_name, context=context)

    def form_valid(self, form):
        form = form.save(commit=False)
        form.user = self.request.user  
        form.save()
        return redirect(self.success_url)

Это возможный дубликат Как установить поле пользователя в форме на текущего вошедшего пользователя?

Есть и другие способы. Например, добавить в форму поле hidden и установить его значение как request.user.id.

Хотя, должен сказать, что ваша первоначальная мысль, связанная с методом save(), правильная. Однако не переопределять его, а использовать необязательное ключевое слово, предоставляемое самим методом.

Также не забудьте установить данные формы и validate ее, что является одной из главных особенностей:

class AddArticle(View):
    ...

    def post(self, request):
        form = ArticleForm(request.POST)
        if form.is_valid():
            instance = form.save(commit=False)
            instance.author = request.user
            instance.save()
        return redirect('index')
Вернуться на верх