我有一个有两种类型用户的Django应用程序,我们称之为A和B.这两种用户类型有不同的导航栏。用户类型A在其导航栏中有一个链接,允许他们发送消息。发送消息表单以叠加形式出现,因此表单需要存在于每个模板中,或通过AJAX获取。这些用户可以从站点上的任何/每个页面发送消息,并且每个页面都有自己的视图。如果邮件有错误,则应将用户返回到他们所在的同一页面,并且错误应显示在表单覆盖中。如果成功发送,则应将其重定向到显示其消息的新页面。
目前,我已将表单放入一个单独的模板中,该模板包含在用户类型A的所有页面上。我将表单操作指定为名为send_message的视图,并且我已告知该视图呈现给此模板。视图永远不会被调用,所以我想这不是正确的方法。
如何在每个模板中呈现此表单?我是否需要从每个视图调用一个函数,或者使用一个特殊的模板标记(我查看了包含标记,但我不认为它们适合这种情况)?或者我应该使用AJAX获取表单?我是否将表单视图添加到每个URL?
编辑:添加一些代码来解释。
比方说,例如,我在一个页面上有这样一个简单的视图:
@login_required
def index_view(request, place_id):
categories = Category.objects.all()
return render(request, 'places/categories.html', {'place_id': place_id, 'categories': categories})
此页面的模板是从包含导航栏的模板扩展而来的,该模板包含发送消息表单,如下所示:
<div id="message-popup">
<h1>NewMessage</h1>
<form action="{% url "send_message" %}" method="post">
{% csrf_token %}
{% get_message_form as message_form %}
<table>
<tr>
<td>{{ message_form.recipient.label_tag }}{{ message_form.recipient }}</span></td>
<td>{{ message_form.title.label_tag }}{{ message_form.title }}</td>
</tr>
<tr>
<td>{{ message_form.categories.label_tag }}{{ message_form.categories }}</td>
<td>
{{ message_form.content.label_tag }}{{ message_form.content }}
<button type="submit" class="button">Send</button>
<button class="box-close button">Cancel</button>
</td>
</tr>
</table>
</form>
</div>
该表单发布到此视图:
def send_message_view(request, place_id):
place = Place.objects.get(id=place_id)
if request.POST:
user = get_user_class(request.user)
message_form = forms.SendMessageForm(request.POST, place=place, user=user)
if message_form.is_valid():
message_form.save()
# redirect to page showing the message
else:
message_form = forms.SendMessageForm(place=place, user=user)
return render(request, 'messaging/send_message_form.html', {'message_form': message_form})
我缺少的步骤是如何让表单首先呈现。当我进入类别页面时,表单不存在 - 显然是因为上下文中没有message_form变量。那么我可以将我的send_message_view和我的index_view运行并渲染两个模板,还是有其他方法我必须将它们全部链接在一起?
编辑:
好的,现在这是我的模板标签:
@register.inclusion_tag('messaging/send_message_form.html', name='get_message_form', takes_context=True)
def get_message_form(context, place, sender, recipient):
message_form = SendMessageForm(context['request'].POST or None, place=place, sender=sender, recipient=recipient)
url = None
if context['request'].method=='POST' and message_form.is_valid():
message = message_form.save()
url = reverse('conversation', kwargs={'place_slug': place.slug, 'message_id': message.id})
""" This doesn't work
return HttpResponseRedirect(url) """
return {'message_form': message_form, 'place_id': place.id, 'message_sent_url': url}
我无法从模板标签中执行HttpResponseRedirect,因此我需要找到一些重定向到成功页面的方法。我可以将重定向网址发送到模板,但我不知道从那里可以用它做什么......
答案 0 :(得分:2)
您希望自定义包含标记呈现您的表单。
@register.inclusion_tag('<your-form-render-template.html>')
def get_message_form(place_id, user):
return {'message_form': SendMessageForm(Place(id=place_id), user)}
然后在index.html模板中:
{%load my-template-tags%}
<div id="message-popup">
<h1>NewMessage</h1>
{%get_message_form place_id request.user%}
</div>
您在标签上注册的模板文件然后呈现表单:
<form action="{% url "send_message" %}" method="post">
{% csrf_token %}
<table>
<tr>
<td>{{ message_form.recipient.label_tag }}{{ message_form.recipient }}</span></td>
<td>{{ message_form.title.label_tag }}{{ message_form.title }}</td>
</tr>
<tr>
<td>{{ message_form.categories.label_tag }}{{ message_form.categories }}</td>
<td>
{{ message_form.content.label_tag }}{{ message_form.content }}
<button type="submit" class="button">Send</button>
<button class="box-close button">Cancel</button>
</td>
</tr>
</table>
</form>
现在,只要您想放置表单,只需加载标记并将正确的args传递给模板标记即可。吊杆!
添加标记有特定要求,例如应用结构等。请阅读here。
更新:
好的,这很酷。您可以将上下文变量添加到包含标记中。现在你的标签看起来像这样:
@register.inclusion_tag('<your-form-render-template.html>', takes_context=True)
def get_message_form(context):
message_form = forms.SendMessageForm(context['request'].POST or None, place=context['place_id'], user=context['request.user'])
if context['request'].method=='POST' and message_form.is_valid():
#redirect to thanks
return {'message_form': SendMessageForm(Place(id=place_id), user)}
现在,您的包含标记与旧表单视图功能的用途相同。你的表单现在可以只有一个动作“。”,它不需要在表单上执行任何逻辑,标签就可以了。
请注意,您的模板中存在错误 - 您需要使用{{message_form.errors}}明确显示表单错误。
感谢这个出色的问题 - 以前从未这样做过,而且它非常强大。
最终更新!!!
好的,最后一点帮助,然后你自己:-)它可能没有在重定向上工作,因为这个包含标签只返回要显示的更新的上下文变量。换句话说,一旦你到达这里,你就无法重定向。因此,由于我们只想向用户显示“您成功”的消息,因此请使用messaging框架。
@register.inclusion_tag('messaging/send_message_form.html', name='get_message_form', takes_context=True)
def get_message_form(context, place, sender, recipient):
from django.contrib import messages
message_form = SendMessageForm(context['request'].POST or None, place=place, sender=sender, recipient=recipient)
url = None
if context['request'].method=='POST' and message_form.is_valid():
message = message_form.save()
messages.add_message(context['request'], messages.INFO, "Dante Rules!")
return {'message_form': message_form, 'place_id': place.id, 'message_sent_url': url}
现在该消息将在您的主模板中提供,因此您可以在使用包含标记呈现表单后检查它:
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
一旦渲染,它就会从上下文中消失,这对我们的情况来说是完美的。所以,你可以在JQuery UIDialog,页面的另一部分或其他任何部分中显示它。它看起来比重新直接的恕我直言更好,因为你留在你发送消息的同一页面。