Django:如何在新模板中的另一个模型上使用 CreateView 的 form_valid() 返回的响应?

Posted

技术标签:

【中文标题】Django:如何在新模板中的另一个模型上使用 CreateView 的 form_valid() 返回的响应?【英文标题】:Django : How can I use the response returned by form_valid() of a CreateView on another model in a new template? 【发布时间】:2019-06-27 10:29:49 【问题描述】:

我正在学习Django,我确信解决方案很简单但我找不到; 我有一个需要按请求过滤的模型“配置文件”。请求和答案需要保存在数据库中。但我不希望用户随时看到所有个人资料。 所以我写了两个模型:第一个包含请求(MyRequest),第二个包含潜在答案(Profile)。在 Django admin 中导入 csv 创建配置文件。 我编写了一个运行良好的代码,但我不知道如何在模板中发送我的响应以使用所有自定义和证券作为 csrf_token。

目前它在与请求相同的 url 中显示响应,我被阻止了

我曾尝试将 get_succes_url 与 HttpResponseRedirect 一起使用,通常我可以在成功 url 中使用 (?P\d+)/$' 来执行此类操作,但它不起作用可能是因为这两个模型不共享任何密钥? 我试图输入成功的网址,但我认为我做错了什么

"""Models"""
class Profile(models.Model):#probgerme probpvt probservice probATCDpvt probATCDbmr probNB
    profname= models.CharField(max_length=20)
    bq = models.ForeignKey(Bq, on_delete=models.CASCADE)#, blank=True
    test1 = models.CharField(max_length=100)
    test2 = models.CharField(max_length=100)
    test3 = models.CharField(max_length=100)

class MyRequest(models.Model):#probgerme probpvt probservice probATCDpvt probATCDbmr probNB
    reqname = models.CharField(max_length=20)
    bq = models.ForeignKey(Bq, on_delete=models.CASCADE)
    user = models.ForeignKey(settings.AUTH_USER_MODEL,default=0, related_name="user2")
    test1 = models.CharField(max_length=100)
    test2 = models.CharField(max_length=100)

"""Forms"""
class MyRequestCreateForm(forms.models.ModelForm):
    class Meta:
        model = MyRequest
        fields = ('bq','test1','test2')
    def save(self, *args, **kwargs):       
        myrequest = super().save(*args, **kwargs)
        myrequest.save()

"""URL """
url(r'^essai_create/$', views.MyRequestCreateView.as_view(), name='my_request'),


"""Views"""
class MyRequestCreateView(LoginRequiredMixin, generic.CreateView): 
    form_class = MyRequestCreateForm
    model = MyRequest
    def get_queryset(self):      
        queryset = super().get_queryset().filter(user=self.request.user)
        return queryset

    def get_form(self, form_class=None):
       form = super().get_form(form_class)
        form.fields['test1'].required = True 
        return form

    def form_valid(self, form):
        form.instance.user = self.request.user 
        self.object = form.save()
        data = form.cleaned_data
        test1 = data['test1']
        test2 = data['test2']

        print('data',data)
        try:
            Profile.objects.get(test1 = test1, test2 = test2 )
            tested3= Profile.objects.get(test1 = test1, test2 = test2).test3.split(',')

        except ObjectDoesNotExist:
            tested3 = ['nothing']*5           

        reponse = "Votre requête : test1 = " + test1 + ", test2 = " + test2 +    "<br>val1, "+tested3[0] + "<br>val2, "+tested3[1] + "<br>val3 " + tested3[2]+ "<br>val4, " + tested3[3]
        return HttpResponse(reponse)

"""Template myrequest_form.html"""

% extends 'base2.html' %
% load bootstrap %
% load crispy_forms_tags %
% load static %
% block content %

<div class="container ">
  <form method="POST" enctype="multipart/form-data" id="project-form">
    % csrf_token %


    <form method="post" >
    % csrf_token %
     form.bq|as_crispy_field 
    <br>
      <div class="col-6">
        Information sur le test1  form.test1  <br>
      </div>
        <br>
      <div class="col-6">
        Information sur le test2  form.test2 <br>
      </div>
        <br>

<br><br>
         <button id = "submitRequest" aria-pressed="true" class="btn btn-primary active" onclick="showPleaseWait()"  type="submit"   >Check for best answer</button>
  </form>


  </form>
</div>
% endblock %

目前在http://localhost:8000/myapp/essai_create/ 中打开的模板中单击“检查最佳答案”按钮后,此网址相同 http://localhost:8000/myapp/essai_create/ 显示: Votre requête : test1 = nouveau, test2 = Rouge 价值 1, 7 验证 2, 12 验证 3, 4 val 4, 5

【问题讨论】:

很遗憾,您的问题并不清楚。该输出有什么问题?你想发生什么?这与 CSRF 代币有什么关系? 非常感谢您的评论,这个输出很好,但它与请求在同一个 url 上,因此它不能使用带有 base.html 和 crsf 的特定 template.html令牌。我不知道如何将此答案传递给新 url 中的新模板,因为我没有在 url 中使用的公用密钥 (pk) 【参考方案1】:

不幸的是,我仍然很难理解您想要什么。也许您想要的是找到与提交数据匹配的 Profile,然后重定向到它?在这种情况下,您需要在 form_valid 中执行该重定向,并为您重定向到的配置文件定义一个 DetailView。所以:

class MyRequestCreateView(LoginRequiredMixin, generic.CreateView): 
    ...
    def form_valid(self, form):
        form.instance.user = self.request.user 
        obj = form.save()
        try:
            profile = Profile.objects.get(test1=obj.test1, test2=obj.test2)
            return redirect('profile', pk=profile.id)
        except Profile.DoesNotExist:
            return redirect('/')   # or wherever

class ProfileDetail(LoginRequiredMixin, generic.DetailView):
    model = Profile

和网址:

path('profile_detail/<int:pk>', ProfileDetail, name='profile')

【讨论】:

再次非常感谢您,这确实是我想做的;它非常有效,但如果我写“obj = form.save()”然后“Profile.objects.get(test1=obj.test1, etc)”本地主机回答“NoneType”对象没有属性“test1”,实际上形式是设置为有效,self 为某个内部地址的 MyRequestCreateView 对象,obj 为 None 和... 因此,对于第一个问题,问题出在您的表单保存方法中,该方法不返回对象。无论如何,该方法毫无意义,您应该将其删除并让它使用默认实现。对于第二个问题,您确定在测试时没有创建重复的配置文件吗? ...如果我使用 "data=form.cleaned_data" 和 test1=data['test1']" 等,那么 Profile.objects.get('test1'=test1, etc) 它会回答“get() 返回了多个 ProbasProfile - 它返回了 3!” 并且确实找到了“args () clone QuerySet [, , 但我确信每个可能的测试组合都有一个配置文件所以我非常绝望! 是的,正如我所说,您显然拥有多个用于该组合的配置文件,可能是在测试期间创建的。 我不明白你在这里的困惑。这与任何此代码甚至您的问题都没有任何关系。您只有三个具有相同值的对象 test1 和 test2。您应该进入管理员并删除重复项。【参考方案2】:

@Daniel Roseman 解决方案(创建一个简单的 ProfileDetail 视图)很棒!我只需要更改路径(我使用的是 Django 2.11)

url(r'profiledetail/(?P<pk>\d+)$', views.ProfileDetail.as_view(), name='profile')

并且需要更改创建视图

def form_valid(self, form):
    form.instance.user = self.request.user 
    self.object = form.save()
    data = form.cleaned_data
    test1 = data['test1']
    test2 = data['test2']
    profile=ProbasProfile.objects.get(test1 = test1, test2=test2)
    return redirect('profile', pk=profile.id)

然后在为答案创建的新模板中

profile.test1profile.test2profile.test3

当然还有他写的 ProfileDetail 类

【讨论】:

以上是关于Django:如何在新模板中的另一个模型上使用 CreateView 的 form_valid() 返回的响应?的主要内容,如果未能解决你的问题,请参考以下文章

在 django 模板中的另一个大括号内使用大括号

当更新同一模型中的另一个特定字段时,如何更新 Django models.DateTimeField?

如何让下拉选择从 Django 模型中填充模板中的 DataTables 表?

将pk传递到Django中的另一个模板

如何将 HTML 文件注入 Django 中的另一个 HTML 文件?

我们可以格式化模型表单如何在模板上的 Django 中显示吗