模板标签不与csrf_token一起使用

时间:2017-06-06 15:46:04

标签: django forms templates tags csrf

我正在尝试创建自定义模板标记以显示评论。当我尝试通过每条评论附带的表单提交回复时,我收到错误:

禁止(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>

1 个答案:

答案 0 :(得分:1)

由于您在标记中手动呈现模板,因此需要使用RequestContext以运行上下文处理器 - 包括添加CSRF令牌的处理器。

return t.render(RequestContext(context['request'], {
                     ...
                }))

请注意,使用inclusion tag可以大大简化整个过程。