【问题标题】:Include form in multiple templates for GenericForeignKey model (CBV)在 GenericForeignKey 模型 (CBV) 的多个模板中包含表单
【发布时间】:2016-04-07 12:06:17
【问题描述】:

为了了解有关 Django 的更多信息并了解如何尽可能地进行 DRY 编程,我正在构建一个具有几个功能的小型网站:

  • 发布博客
  • 发布图片
  • 发表书签

在这些应用程序中的每个对象上,用户都可以发表评论。所以我得到了 一个带有 GenericForeignKey 模型的评论 APP。 (正常工作)

我想在博客、图片和书签的详细信息视图中显示评论表单。为了保持干燥,我创建了一个包含标签

@register.inclusion_tag('comments/add_comment.html')
def show_comment_form(obj):
    pk = obj.pk
    content_type = ContentType.objects.get_for_model(obj)
    form = AddCommentForm()

    return {'pk': pk, 'content_type': content_type, 'form': form}

它使用以下模板来呈现表单:

<form action="{% url 'comments:add' pk content_type %}" method="post">
    <div class="create-blog-container">
        <div class="box-top">{% trans "Leave your comment behind" %}...</div>
        <div class="box-content">
            {% csrf_token %}
            {{ form.as_div }}
        </div>
        <div class="box-footer">
            <input type="submit" class="btn btn-green" value="{% trans 'Add comment' %}" />
        </div>
</form>

添加时

{% show_comment_form blog %} 

在博客的详细模板中,它使用正确的参数呈现表单。当我点击 SUBMIT 按钮时,表单将在以下添加视图中处理(目前只是获取表单、验证并通过服务将其添加到数据库中)。

class Add(LoginRequiredMixin, View):
    model = Comment

    def post(self, *args, **kwargs):
        content_type = self.kwargs.get('content_type')
        pk = self.kwargs.get('pk')
        form = AddCommentForm(self.request.POST)

        if form.is_valid():
            content = form.cleaned_data.get('content')
            comments.services.comment.add(content_type, pk, self.request.user, content)
            messages.add_message(self.request, messages.SUCCESS, _("Your comment has been posted"))
        else:
            print(form.errors)

        return HttpResponseRedirect(reverse('blogs:detail', kwargs={'pk': pk}))

但此解决方案不会呈现带有验证错误的表单。我回到基础,在博客的详细视图中创建了一个“硬编码”表单,但它既不灵活也不干。

谁能给我一个正确的方向推动如何将此表单(通过包含标签或其他建议的方法)转换为 DRY 和灵活的表单以发表对通用 content_type 的评论?

【问题讨论】:

    标签: python django forms generics django-class-based-views


    【解决方案1】:

    为了完成 DRY,我建议(如您所述)为 Django contenttypes 实施评论并将其与 AJAX 混合。

    对于您的情况,可以将经过验证的表单传递给您的包含标签 (show_comment_form)

    @register.inclusion_tag('comments/add_comment.html')
    def show_comment_form(obj, form=None):
        pk = obj.pk
        content_type = ContentType.objects.get_for_model(obj)
        form = form or AddCommentForm()
    
        return {'pk': pk, 'content_type': content_type, 'form': form}
    

    【讨论】:

      【解决方案2】:

      更改您的包含标签,因此它将根据对象类型在不同的 URL 上发表评论。还要更改它,因此如果当前上下文中已经存在comment_form,它将不会生成新形式。示例:

      @register.inclusion_tag('comments/add_comment.html', takes_context=True)
      def show_comment_form(context, obj):
          pk = obj.pk
          content_type = ContentType.objects.get_for_model(obj)
          form = context.get('comment_form', AddCommentForm())
      
          url_id = "%s:%s:comment:add" % (content_type.app_label, content_type.model)
      
          return {'pk': pk, 'content_type': content_type, 'form': form, url_id}
      

      模板:

      {# content_type may be obsolete now #}
      <form action="{% url url_id pk content_type %}" method="post">
          <div class="create-blog-container">
              <div class="box-top">{% trans "Leave your comment behind" %}...</div>
              <div class="box-content">
                  {% csrf_token %}
                  {{ form.as_div }}
              </div>
              <div class="box-footer">
                  <input type="submit" class="btn btn-green" value="{% trans 'Add comment' %}" />
              </div>
      </form>
      

      创建视图 mixin,它将添加到您的视图处理评论创建(或表单验证),从该内容的正常视图和您的新 mixin 为您的每种内容类型创建新视图,并在单独的 URL 上注册该视图(名称您在模板标签中创建url_id 的方式)。

      它干爽、灵活,不需要太多改动。

      【讨论】:

        猜你喜欢
        • 2013-10-02
        • 2013-05-30
        • 2013-09-26
        • 1970-01-01
        • 2017-12-04
        • 1970-01-01
        • 2012-06-16
        • 2011-07-14
        • 1970-01-01
        相关资源
        最近更新 更多