【问题标题】:Can I somehow call logic from form_valid() in Django tests?我可以在 Django 测试中以某种方式从 form_valid() 调用逻辑吗?
【发布时间】:2019-05-29 01:33:36
【问题描述】:

我正在尝试在我的简单论坛应用程序中测试用于创建帖子模型的表单。我遇到的问题是,在我尝试在测试中保存表单后,我收到错误NOT NULL constraint failed: forum_web_post.user_id,因为我在视图中的form_valid() 方法中分配了用户。用户不会通过表单传递,因为创建帖子的用户是发送请求的登录用户。

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)

用户是从django.contrib.auth.models 导入的,类别模型如下所示。

class Category(models.Model):
    name = models.CharField(max_length=100)
    created_at = models.DateTimeField(auto_now=True)

views.py 中,用户提交表单后,他被重定向到他的个人资料页面

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())

任何帮助将不胜感激!

【问题讨论】:

    标签: python django django-forms django-testing


    【解决方案1】:

    您只是在测试表单。所以在你的测试中调用视图函数是没有意义的。在将表单保存在测试中之前,您应该使用 form.instance.user = ... 手动将用户分配给表单的实例,因为这是应该使用表单的方式。

    此外,您应该通过实际登录用户并将请求发布到PostCreate 视图来测试您的视图。在这里,您正在测试视图是否正确保存了表单(以及您的 form_valid() 方法是否正常工作)。

    注意:post.user = self.request.user 比使用 id 从数据库中重新获取用户要好。这是多余的。

    【讨论】:

    • 像魅力一样工作!非常感谢!即使我真的不知道该实例做了什么。您介意解释一下为什么它现在有效吗?
    • 表单是ModelForm,所以instance 是表单将保存的实际Post 实例。当您在视图中执行post = form.save(commit=False) 时,您将获得表单的实例。
    猜你喜欢
    • 1970-01-01
    • 2015-07-05
    • 2011-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多