While creating my website, I face the following problem: a user can add an article, and so the article model has a ForeignKey field - author.
I created a form for adding it, inheriting from ModelForm, since I think it is more logical that way (as it interacts directly with db). The problem is that I cannot add this field to the Form, as it cannot be filled; it has to be taken from the request itself.
author = request.user.pk
So how can I make a form save the author id as well? Without it, there's an error: NOT NULL CONSTRAINT FAILED
, which is logical as the form doesn't save pk and so it is null; but a FOREIGN KEY
cannot be null.
The only way is to inherit it from class Form? I don't really want to do it... I was thinking about 'overriding' method save()
so that it has one more argument - author id:
form.save(author=request.user.pk)
This way it would work. But I changed my mind, because if something goes wrong, this will mess up the whole database... The save()
method is too global. What's more, there might well be another way to solve my problem, which is more effective and clear.
Here's the code for my form:
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...' })}
and my model:
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()
and my view:
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')
It seems that I completely misunderstand the basics of ModelForm creation...
There are other ways. Such as adding a hidden
field to your form and set its value as the request.user.id
.
Although, I must say that your initial thought related to the save()
method is the correct one. However, not overriding it but using an optional keyword provided by the method itself.
Also, do not forget to set form data and validate
it, which is one of the main features:
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')