I am trying to test form for Post model creation in my simple forum application. The problem I am having is that after I try to save the form in tests I get an error NOT NULL constraint failed: forum_web_post.user_id
because I am assigning the user in the form_valid()
method in the view. The user is not passed via the form since the user that creates the post is the signed in user that sent the request.
models.py
class Post(models.Model):
category = models.ForeignKey(Category, on_delete=models.PROTECT)
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
text = models.TextField()
created_at = models.DateTimeField(auto_now=True)
user is imported form django.contrib.auth.models
and Category model looks like this.
class Category(models.Model):
name = models.CharField(max_length=100)
created_at = models.DateTimeField(auto_now=True)
in views.py
after the user submits the form he is the redirected to his profile page
views.py
class PostCreate(generic.CreateView):
model = Post
form_class = PostForm
template_name = 'forum_web/post_edit.html'
def form_valid(self, form):
post = form.save(commit=False)
post.user = models.User.objects.get(id=self.request.user.id)
post.save()
return HttpResponseRedirect(reverse_lazy('forum:user_detail', kwargs={'pk': self.request.user.id}))
forms.py
class PostForm(ModelForm):
class Meta:
model = Post
fields = ['category', 'title', 'text']
tests.py
def test_post_form_create_should_pass(self):
# this dict is in setUp() as well as the test_category but for simplicity I will include it in this method
post_data = {
'category': self.test_category.pk,
'title': 'test_post',
'text': 'test_post_text'
}
post_count = Post.objects.count()
form = PostForm(data=self.post_data)
self.assertTrue(form.is_valid())
form.save()
self.assertEqual(post_count + 1, Post.objects.count())
any help would be appreciated!
You are just testing the form. So it doesn't make sense to call a view function in your test. You should manually assign a user to the form's instance using form.instance.user = ...
before saving the form in your test, since that's the way the form should be used.
In addition, you should test your view by actually logging in a user and posting the request to the PostCreate
view. Here you're testing that the view correctly saves the form (and that your form_valid()
method works correctly).
Note: post.user = self.request.user
would be better than re-fetching the user from the database using the id
. It's redundant.