我正在尝试创建自定义模板标记以显示评论。当我尝试通过每条评论附带的表单提交回复时,我收到错误:
禁止(403) CSRF验证失败。请求中止。 失败的原因: CSRF令牌丢失或不正确。
csrf令牌在带有下载和关注按钮的表单上工作,但不在从模板标记生成的表单上。任何帮助将不胜感激。
DocumentView
def DocumentView(request, doc_id):
context = {}
user = None
if request.user.is_authenticated():
email = request.user.email
id = request.user.id
user = get_user_information(email=email)
else:
user = None
context['user'] = user
if request.method == 'POST':
user_id = request.POST.get('submit', '')
doc = Doc.objects.get(id=doc_id)
doc_version = DocVersion.objects.filter(doc__id=doc_id).latest('id')
doc_title = doc.response_title
allow_comments = doc.allow_comments
comments = {}
if user['user_type'] == 'DA':
for comment in Comment.objects.filter(doc_id=doc_id):
comments[comment.id] = {'content': comment.content, 'reply_to': comment.reply_to, 'user_id': comment.user.id}
else:
for comment in Comment.objects.filter(doc_id=doc_id, is_flagged=False):
comments[comment.id] = {'content': comment.content, 'reply_to': comment.reply_to, 'user_id': comment.user.id}
context['comments'] = comments
context['allow_comments'] = allow_comments
context['doc_title'] = doc_title
print context
return render(request, 'doc/document.html', context)
comment_tags.py
from django.template import Library, Node, Context, Variable
from django.template.loader import get_template
from django import template
register = Library()
@register.tag()
def comments(parser, token):
user_id, profile_pic, reply_id, comment_id, content, info = None, None, None, None, "", ""
for index, x in enumerate(token.split_contents()):
if x == 'user_id':
user_id = token.split_contents()[index + 1]
if x == 'profile_pic':
profile_pic = token.split_contents()[index + 1]
if x == 'content':
content = token.split_contents()[index + 1]
if x == 'info':
info = token.split_contents()[index + 1]
if x == 'reply_id':
reply_id = token.split_contents()[index + 1]
if x == 'comment_id':
comment_id = token.split_contents()[index + 1]
return CommentNode(user_id, profile_pic, comment_id, content, info, reply_id)
class CommentNode(template.Node):
def __init__(self, user_id, profile_pic, comment_id, content, info, reply_id):
self.user_id = template.Variable(user_id)
self.profile_pic = template.Variable(profile_pic)
self.content = template.Variable(content)
self.info = template.Variable(info)
self.comment_id = template.Variable(comment_id)
if reply_id != None:
self.reply_id = template.Variable(reply_id)
else:
self.reply_id = reply_id
def render(self, context):
t = get_template("srd/comment.html")
if self.reply_id == None:
return t.render({
'user_id': self.user_id.resolve(context),
'profile_pic': self.profile_pic.resolve(context),
'comment_id': self.comment_id.resolve(context),
'content': self.content.resolve(context),
'info': self.info.resolve(context),
'reply_id': self.reply_id
}
)
else:
return t.render({
'user_id': self.user_id.resolve(context),
'profile_pic': self.profile_pic.resolve(context),
'comment_id': self.comment_id.resolve(context),
'content': self.content.resolve(context),
'info': self.info.resolve(context),
'reply_id': self.reply_id.resolve(context)
})
document.html
{% load static %}
{% load comment_tags %}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ doc_title }}</title>
<link rel="stylesheet" type="text/css" href="{% static "stylesheets/doc.css" %}">
<script src="{% static "javascript/jquery-3.2.1.min.js" %}" type="text/javascript"></script>
<script src="{% static "javascript/doc.js" %}" type="text/javascript"></script>
</head>
<body>
<div class="main_div">
<div class="content_div">
<div class="info_div">
<h2>[{{ generic_name }}]</h2>
<label>{{ doc_title }} <a href="edit">[Edit]</a></label>
</div>
<div class="doc_div">
<div class="doc_preview">
</div>
<div class="doc_preview_info">
<form method="post">
{% csrf_token %}
<input type="hidden" value="{{ user.id }}" />
<input type="submit" value="Donwload PDF" /><br/>
<input type="submit" value="Follow" />
</form>
</div>
</div>
{% if allow_comments %}
<div class="comment_div" id="comment_div">
{% for commentid, comment in comments.items %}
{% if comment.reply_to %}
{% comments comment_id commentid user_id comment.user_id reply_id comment.reply_to.id profile_pic "hi" content comment.content info "XYZ" %}
{% else %}
{% comments comment_id commentid user_id comment.user_id profile_pic "hi" content comment.content info "XYZ" %}
{% endif %}
{% endfor %}
</div>
{% endif %}
</div>
<div class="ad_div">
<div class="ad"></div>
<div class="ad"></div>
<div class="ad"></div>
<div class="ad"></div>
</div>
</div>
</body>
</html>
comment.html
<div class="comment">
<div class="profile_pic">
{{ user_id }}
</div>
<div class="comment_content">
<div class="top_bar">
<div class="comment_info">
{{ info }}
</div>
<div class="flag">
<a href="#">Flag</a>
</div>
</div>
<div class="comment_text">
{{ content }}
</div>
<div class="reply_bar">
<a id="reply_link_{{ comment_id }}" class="reply_link" href="#">Reply</a>
</div>
</div>
</div>
<div class="reply" id="reply_{{ comment_id }}">
<form method="post">
{% csrf_token %}
<input type="hidden" value="{{ reply_id }}"/>
<input name="reply_text" type="text" />
<input type="submit" value="Post" />
</form>
</div>
答案 0 :(得分:1)
由于您在标记中手动呈现模板,因此需要使用RequestContext以运行上下文处理器 - 包括添加CSRF令牌的处理器。
return t.render(RequestContext(context['request'], {
...
}))
请注意,使用inclusion tag可以大大简化整个过程。