【发布时间】:2017-02-21 05:32:40
【问题描述】:
在我搭建的一个 Django 社交网站中,用户可以在普通房间里聊天,或者创建私人群组。
每个用户都有一个主仪表板,他们参与的所有对话都显示在一起,彼此堆叠(按 20 个对象进行分页)。我称之为unseen activity 页面。此页面上的每个看不见的对话都有一个文本框,用户可以直接在其中输入回复。此类回复通过 <form> 内的 POST 请求提交。
每个<form> 的action 属性指向不同的网址,具体取决于提交的回复类型(例如home_comment 或group_reply)。这是因为它们有不同的验证和处理要求等。
问题是这样的:如果引发了 ValidationError(例如,用户输入了带有禁止字符的回复),它会显示在unseen_activity 中的多个表单上页面,而不仅仅是生成它的特定表单。如何确保所有 ValidationErrors 仅出现在它们起源的表单上?一个说明性的例子会很棒!
附加到所有这些的表单类称为UnseenActivityForm,并定义如下:
class UnseenActivityForm(forms.Form):
comment = forms.CharField(max_length=250)
group_reply = forms.CharField(max_length=500)
class Meta:
fields = ("comment", "group_reply", )
def __init__(self,*args,**kwargs):
self.request = kwargs.pop('request', None)
super(UnseenActivityForm, self).__init__(*args, **kwargs)
def clean_comment(self):
# perform some validation checks
return comment
def clean_group_reply(self):
# perform some validation checks
return group_reply
模板如下所示:
{% for unseen_obj in object_list %}
{% if unseen_obj.type == '1' %}
{% if form.comment.errors %}{{ form.comment.errors.0 }}{% endif %}
<form method="POST" action="{% url 'process_comment' pk %}">
{% csrf_token %}
{{ form.comment }}
<button type="submit">Submit</button>
</form>
{% if unseen_obj.type == '2' %}
{% if form.group_reply.errors %}{{ form.group_reply.errors.0 }}{% endif %}
<form method="POST" action="{% url 'process_group_reply' pk %}">
{% csrf_token %}
{{ form.group_reply }}
<button type="submit">Submit</button>
</form>
{% endif %}
{% endfor %}
现在是观点。我不会一次性处理所有内容。一个函数负责为 GET 请求生成内容,其他函数负责处理 POST 数据处理。如下:
def unseen_activity(request, slug=None, *args, **kwargs):
form = UnseenActivityForm()
notifications = retrieve_unseen_notifications(request.user.id)
page_num = request.GET.get('page', '1')
page_obj = get_page_obj(page_num, notifications, ITEMS_PER_PAGE)
if page_obj.object_list:
oblist = retrieve_unseen_activity(page_obj.object_list)
else:
oblist = []
context = {'object_list': oblist, 'form':form, 'page':page_obj,'nickname':request.user.username}
return render(request, 'user_unseen_activity.html', context)
def unseen_reply(request, pk=None, *args, **kwargs):
if request.method == 'POST':
form = UnseenActivityForm(request.POST,request=request)
if form.is_valid():
# process cleaned data
else:
notifications = retrieve_unseen_notifications(request.user.id)
page_num = request.GET.get('page', '1')
page_obj = get_page_obj(page_num, notifications, ITEMS_PER_PAGE)
if page_obj.object_list:
oblist = retrieve_unseen_activity(page_obj.object_list)
else:
oblist = []
context = {'object_list': oblist, 'form':form, 'page':page_obj,'nickname':request.user.username}
return render(request, 'user_unseen_activity.html', context)
def unseen_group_reply(group_reply, pk=None, *args, **kwargs):
#similar processing as unseen_reply
注意:代码是我实际代码的简化版本。如果需要,请询问更多详细信息。
【问题讨论】:
-
请同时添加您正在创建表单和看不见的对象的视图。看起来您对所有看不见的对象使用相同的表单。查看模板,似乎所有表单都使用了相同的 URL。
-
@AKS:确实,你是对的。我也添加了视图,看看。这里有什么解决方法?
-
您需要为每个看不见的活动创建单独的表单,以确保只有与特定活动相关的表单才会显示错误。此外,您在每个表单中使用的
action根本没有使用pkurl 参数。 -
@AKS:抱歉,
action被错误地显示了 - 我已经修改了它(在我的真实代码中,我确实包含了pk)。回复:为每个 unseen_activity 制作单独的表格,这是让我感到困惑的部分。我在 for 循环中生成表单 - 可能有许多看不见的活动(所以我将其分页 20)。我将如何在这里手动创建具有唯一身份的它们?似乎无法绕过它。可以举个例子吗? -
您在 for 循环中使用的
form在视图中创建并通过上下文传递给模板。因此,您对所有看不见的活动使用相同的表单实例。您需要做的是为视图上下文本身中的每个看不见的活动创建一个单独的表单。并且,在表单和活动之间有一个映射,您可以使用它稍后呈现表单。
标签: django django-forms