如何使用测试客户端测试 django (3.0) CreateView 的“form_valid”方法和参数?

Posted

技术标签:

【中文标题】如何使用测试客户端测试 django (3.0) CreateView 的“form_valid”方法和参数?【英文标题】:How to test django (3.0) CreateView's 'form_valid' method and parameters with a test client? 【发布时间】:2021-01-02 16:41:03 【问题描述】:

一些信息

我正在重写 form_valid 方法(出于某种原因)。

我想要做什么

我想测试form_valid 实例,特别是它的参数。为此,我使用Django's test client。

一些代码

models.py:

class MyModel(models.Model):
    my_model_text = models.CharField(max_length=100)
    my_model_date = models.DateTimeField(
        'my model date',
        auto_now_add=True)

views.py:

class CreateMyModelView(LoginRequiredMixin, generic.edit.CreateView):

    model = MyModel
    template_name = 'myapp/create-my-model.html'
    form_class = CreateMyModelForm

    def post(self, request=None, *args, **kwargs):

        # do something here
        form = self.get_form()
        if form.is_valid():
            return self.form_valid(form, request)
        else:
            return self.form_invalid(form)

    def form_valid(self, form, request):

        # do something else here
        my_model_text = form.cleaned_data['my_model_text']
        MyModel.objects.create(my_model_text=my_model_text)

        return redirect(reverse('myapp:mypage'))

forms.py:

class CreateMyModelForm(forms.ModelForm):

    class Meta:
        model = MyModel
        fields = ['my_model_text']

tests.py:

class CreateMyModelViewTests(TestCase):

    @classmethod
    def setUpTestData(cls):

        cls.my_auth_user = User.objects.create(
            username='my_auth_user')
        cls.my_auth_user.set_password('my_auth_password')
        cls.my_auth_user.save()

    def test_form_valid(self):

        client = self.client
        client.login(
            username='my_auth_user',
            password='my_auth_password')
        # post response ? #

问题

如何测试form_valid 使用测试客户端获取的参数(不是form 对象的实例,而是form_valid 方法本身)?

【问题讨论】:

您发布的代码似乎都没有提到session...当然您知道request.user 将持有对当前登录用户的引用,如果这是您存储的信息? 【参考方案1】:

由于 CBV 将当前请求存储为 self.request,因此您无需更改 form_valid 的签名。

我认为您的视图可以/应该简化为这样的内容(如您所见,form_valid() 中也只有注释掉的内容,因此您可以完全省略它,除非您需要使用例如修改实例请求用户)。

class CreateMyModelView(LoginRequiredMixin, CreateView):
    model = MyModel
    template_name = 'myapp/create-my-model.html'
    form_class = CreateMyModelForm
    success_url = reverse_lazy('myapp:mypage')

    def form_valid(self, form):
        # You can modify the object-to-be-saved before saving, e.g.
        # form.instance.creator = self.request.user

        # The CreateView implementation just calls `form.save()` and redirects away,
        # so let's reuse that.
        return super().form_valid(form)

【讨论】:

嗨@AKX 非常感谢您的回答:) (1) 自从我发布了这个我改变了我的设计,正如你所建议的,现在 form_valid() 没有被覆盖。 (2) 关于您的评论 - 我不是试图获取用户信息,而是试图为用户保存“环境状态”。 (3) 我的问题不涉及 form_valid() 的使用,它涉及测试(使用测试客户端测试我决定覆盖的任何方法)。那么,假设我决定重写某个方法 - 测试其参数的唯一方法是也重写调用它的方法吗? 我很抱歉@AKX,你完全正确,我忘了更新这个问题,以及我以这种方式离开帖子的原因。我清理了所有的混乱,我希望现在措辞更好。 你当然可以初始化一个CreateMyModelView 对象并调用实例的form_valid(Django RequestFactory 对象可能会派上用场),但我不太清楚你为什么需要测试那个cf测试视图在发布某些给定数据时是否执行了所需的操作。 用于调试目的。但是我想如果没有一些具体的例子(以及一个有充分理由的例子),这个讨论就变得毫无意义了......所以在我遇到一个具体案例之前 - 我会感谢你的时间和你的答案:) 谢谢

以上是关于如何使用测试客户端测试 django (3.0) CreateView 的“form_valid”方法和参数?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用测试客户端填写 Django 表单

如何使用 django-rest-framework 测试客户端测试二进制文件上传?

Django 测试:如何在 SQLite 上测试并发用户?

如何在 Django 测试客户端中保持 POST 参数的顺序?

使用Django 测试客户端一起测试视图,模板和URL

使用 django 测试客户端发送 JSON