一个模板中一页上的多个评论表单 - Django

Multiple Comment Forms on One Page in One Template - Django

我已经对此进行了研究,许多答案都涉及到它(表单集、前缀等),但 none 正是我所追求的...

我有一个应用程序允许用户将 post 卡片添加到看板,并且每张卡片可以有零个或多个评论。我设置了数据库关系,所以如果我手动添加图板、卡片或评论 objects 我可以在模板中很好地显示它们。

卡片表格也可以使用,所以这不是问题。但现在我想显示带有 click 事件的评论 textarea(我正在处理 jQuery)。问题是,表单没有显示字段。这是表单代码:

class AddCommentForm(ModelForm):
    class Meta:
        model = Comment
        fields = ['message']

    message = forms.CharField(
        widget=forms.Textarea(
            attrs={
                'class': 'form-control comment-input'
                'name': 'message',
                'placeholder': 'Comment away...'
            }
        ),
        required=False,
    )

马上就有一个问题,当 Django 呈现表单时,它使用 id。在这种情况下,它最终是 id_messagemessage(取决于我是否在 class 表格中指定)。当然,在HTML中,这是不行的。我在 shell:

中确认了这一点
>>> import django; import project
>>> from apps.board.forms import AddCommentForm
>>> comment_form = AddCommentForm(); print(comment_form)
<tr><th><label for="message">Message:</label></th><td><textarea class="form-control comment-input" cols="40" id="message" name="message" placeholder="Comment away..." rows="10">
</textarea></td></tr>

所以我想到了使用formsets,但似乎不太正确,因为据我了解,它们在一个form 标签内用于多种形式。我的情况不同,因为每张卡片都有零个或多个评论,HTML 的流程规定应该有几个 form 元素。

另一个挑战是我需要有两个视图:一个处理卡片,一个处理每条评论。我目前正在使用不同的操作值来完成此操作并且它似乎有效。

看来我的用例并没有那么奇怪,我能想到几种会发生这种情况的情况:推特回复,博客评论posts等等。我就是可以'不要让 Django 处理这个。

我还应该注意,我可以用这个手动完成这项工作:

<label>
    <textarea class="form-control comment-input" name="message"></textarea>
    <button type="submit"></button>
</label>

更新

这是一个视图片段:

class AddCommentView(View):

    model = Comment
    form_class = AddCommentForm
    template_name = 'somedir/template.html'

    @method_decorator(login_required)
    def get(self, request):

        comment_form = self.form_class()

        return render(request, self.template_name, {
            'comment_form': comment_form
        })

如果表单正常工作(来自上面的代码片段和 shell 测试),我希望它能显示在页面上。

URL会议在这里:

url(r'^comment/add/$', AddCommentView.as_view(), name='add_comment_view'),

在写这篇文章时,我看到了一个令人困惑的片段。我的视图 URL 是 /comment/add/,但我希望表单呈现在 /dashboard/。问题是 URL 已经有另一个观点了。

如果我在没有 Django 表单的情况下构建表单,则会创建 post 到 /comment/add/ 评论的数据并将其保存在数据库中。所以我想我仍在尝试弄清楚如何在具有多种形式的一个模板中使用两个视图。 @Daniel Roseman 指出 prefix 的使用,我想这值得进一步探索。

更新 2

所以我通过删除该视图的 URL 并将这些视图合并为一个视图来使用前缀来实现它。两种形式,一种视图,一种模板。但是...

来源仍然显示重复 ids。我最终没有将 id 放在表单属性列表中。由于这是无效的 HTML,解决此问题的最佳方法是什么?

在我看来:

card_model = Card
comment_model = Comment

card_form_class = AddCardForm
comment_form_class = AddCommentForm
. . .
@method_decorator(login_required)
def get(self, request):

    card_form = self.card_form_class(prefix='card')
    comment_form = self.comment_form_class(prefix='comment')
    . . .

更新 3

我找到了解决这个问题的方法。实例化窗体,需要添加auto_id=False防止重复,复制ids:

comment_form = self.comment_form_class(prefix='comment', auto_id=False)

您可以在实例化表单时使用 prefix 参数来为它们提供不冲突的 ID。

虽然使用 Django 表单 prefix 是部分正确的(感谢 @Daniel Roseman),但关于我拥有多少表单元素并不重要的断言并不完全正确。它确实很重要,因为默认情况下前缀意味着以一种形式使用(因为它创建多个复制 ids)。要以多种形式使用它,您还需要 auto_id=False。这样可以防止 id 被 Django 表单生成。