在测试期间,如何将django视图GET请求的响应插入到与POST请求相同的视图中?

在测试期间,如何将django视图GET请求的响应插入到与POST请求相同的视图中?,django,python-3.x,django-forms,django-testing,Django,Python 3.x,Django Forms,Django Testing,我有一个基于Django函数的表单视图,它在GET请求中使用默认数据初始化表单,并在POST请求中保存模型对象: def copy(request, ann_id): new_ann = get_object_or_404(Announcement, pk=ann_id) new_ann.pk = None # autogen a new primary key (quest_id by default) new_ann.title = "Copy of " + new

我有一个基于Django函数的表单视图,它在GET请求中使用默认数据初始化表单,并在POST请求中保存模型对象:

def copy(request, ann_id):
    new_ann = get_object_or_404(Announcement, pk=ann_id)
    new_ann.pk = None  # autogen a new primary key (quest_id by default)
    new_ann.title = "Copy of " + new_ann.title
    new_ann.draft = True
    new_ann.datetime_released = new_ann.datetime_released + timedelta(days=7)

    form = AnnouncementForm(request.POST or None, instance=new_ann)
    if form.is_valid():
        new_announcement = form.save(commit=False)
        new_announcement.author = request.user
        new_announcement.datetime_created = timezone.now()
        new_announcement.save()
        form.save()

        return redirect(new_announcement)

    context = {
        "title": "",
        "heading": "Copy an Announcement",
        "form": form,
        "submit_btn_value": "Create",
    }
    return render(request, "announcements/form.html", context)
如果不在我的视图中手动将表单数据提供给
self.client.post(url,form\u data)
,我就不知道如何在发布表单时测试
form.is\u valid()
分支

以下是我正在尝试的:

测试视图.py

class AnnouncementViewTests(TestCase):

    def setUp(self):
        self.client = ...
        ... etc

    def test_copy_announcement(self):
        # log in a teacher
        success = self.client.login(username=self.test_teacher.username, password=self.test_password)
        self.assertTrue(success)

        # hit the view as a get request first, to load a copy of the announcement in the form
        response = self.client.get(
            reverse('announcements:copy', args=[self.test_announcement.id]),
        )
        self.assertEqual(response.status_code, 200)

        # The form in this response should be valid, and should bw
        # accepted on a post request, 
        # that is what I am testing in this integration test.

        form_data = response.how_do_get_the_form_data() # ???????

        response = self.client.post(
            reverse('announcements:copy', args=[self.test_announcement.id]),
            data=form_data
        )

        # Get the newest announcement just made in the post request
        new_ann = Announcement.objects.latest('datetime_created')

        self.assertRedirects(
            response, 
            new_ann.get_absolute_url()
        )
我想要实际测试的是
get
的结果为表单提供了有效的默认数据,然后可以通过
post
请求提交这些数据

但是我不知道如何访问
get
请求产生的表单数据,因此我可以将其输入到提供给
post
请求的表单数据中

编辑

我在get响应中找到了表单的位置,但我不知道如何在代码中找到它


你的问题有点让人困惑,但我会尽力引导你正确的方向

要清理代码,应使用基于类的视图,您可以在任何地方轻松使用表单。我刚刚编写的示例代码:


class TestView(View):
    template_name = 'index.html'
    success_url = 'home' # dummy view
    context = {"form": myform()} 
    # myform is the definition/class of your form which contains all attrs.

    def get(self, request):
        context = self.context
        context['form'] = form # fill out your data here for get request
        return render(request, self.template_name, context)

    def post(self, request):
        context=self.context 
    # self.context certain that you're using exact form which you defined in class-scope
        form=context['form']
        # Form Validation
        if form.is_valid():
            #perform any logical validations here and save the form if required
        return redirect(self.success_url)

        context = self.context
        context['form'] = form # just to show you that you can access that form anywhere
        return render(request, self.template_name, context)

你的问题有点让人困惑,但我会尽力把你引向正确的方向

要清理代码,应使用基于类的视图,您可以在任何地方轻松使用表单。我刚刚编写的示例代码:


class TestView(View):
    template_name = 'index.html'
    success_url = 'home' # dummy view
    context = {"form": myform()} 
    # myform is the definition/class of your form which contains all attrs.

    def get(self, request):
        context = self.context
        context['form'] = form # fill out your data here for get request
        return render(request, self.template_name, context)

    def post(self, request):
        context=self.context 
    # self.context certain that you're using exact form which you defined in class-scope
        form=context['form']
        # Form Validation
        if form.is_valid():
            #perform any logical validations here and save the form if required
        return redirect(self.success_url)

        context = self.context
        context['form'] = form # just to show you that you can access that form anywhere
        return render(request, self.template_name, context)

您可以像这样手动将数据传递给表单,并在单元测试中测试
是否有效
函数:

form_data = {'my': 'value', 'form': 'value', 'fields': 'value'}
form = AnnouncementForm(form_data)
self.assertFalse(form.is_valid)

您可以像这样手动将数据传递给表单,并在单元测试中测试
是否有效
函数:

form_data = {'my': 'value', 'form': 'value', 'fields': 'value'}
form = AnnouncementForm(form_data)
self.assertFalse(form.is_valid)

您可以通过以下方式访问响应表单:

response.context['form']
从这里,您可以通过以下方式构建有效负载:

retrieved_instance=response.context['form'].instance

表单_data=dict(title=retrieved _instance.title,…)以了解主要概念。

您可以通过以下方式访问响应表单:

response.context['form']
从这里,您可以通过以下方式构建有效负载:

retrieved_instance=response.context['form'].instance

表格数据=dict(title=retrieved\u instance.title,…了解主要概念。

对不起,你是对的,这个问题现在让我很困惑,因为我再看一遍。我实际上想在集成测试中测试这个视图。我会添加它。但无论如何,这非常有帮助,谢谢。我一直在努力切换到CBV!是的,但一旦你感到舒服了有了CBV他们会让你的生活变得非常轻松。很高兴我能给你一些想法。如果你的问题现在不需要回答,请确认我的答案并关闭这个。谢谢!它仍然需要回答。问题是关于集成测试的。对不起,你是对的,这个问题现在让我很困惑,我现在再看一遍。我真的很想回答在集成测试中,我将添加此视图。但无论如何,这非常有帮助,谢谢。我一直在努力切换到CBV!是的,但一旦你对CBV感到满意,它们将使你的生活变得非常轻松。很高兴我能给你一些想法。如果你的问题不需要现在回答,请确认我的答案并关闭此。谢谢!它仍然需要这是一个答案。这个问题是关于集成测试的。我将在这里进行集成测试。正如问题中提到的:“…不手动提供表单数据”。我已经用更多信息澄清了这个问题。我将在这里进行集成测试。正如问题中提到的:“…不手动提供表单数据”。我已经用更多的信息澄清了这个问题。有没有办法只将
检索到的\u实例
字段值复制到dict中,而不手动列出所有字段?您可以使用
response.context['form'].initial
,即dict,而不是
response.context['form'].instance
这太接近了!
initial
几乎可以直接插入,除了它包含post请求抱怨的一些值,如
None
。有没有办法只将
检索到的\u instance
字段值复制到dict中而不手动列出所有字段?您可以使用
response.contentxt['form'].initial
,这是一个dict,而不是
response.context['form'].instance
这太接近了!
initial
几乎可以直接插入,只是它包含一些post请求抱怨的值,如
None