如何在POST-超链接中使用csrf-token?

How to use csrf-token in POST-hyperlink?

我需要在 Django 中为 POST 请求创建一个超链接。例如,菜单中的“添加到黑名单”。使用带有提交按钮的表单很容易,但我需要一个菜单​​项而不是按钮。我找到了执行此操作的 Javascript 代码,但它给我一个错误 403:CSRF 令牌丢失或不正确。而且我找不到关于如何将 csrf-token 插入 Javascript 函数的信息。我不知道Javascript,我写在Python.

这是来自 https://ru.whosebug.com/questions/65237/Вызов-метода-post-через-ссылку 的函数:

    <script type="text/javascript">
        function postToUrl(path, params, method) {
            method = method || "post"; 

            var form = document.createElement("form");
            form.setAttribute("method", method);
            form.setAttribute("action", path);
            for(var key in params) {
                var hiddenField = document.createElement("input");
                hiddenField.setAttribute("type", "hidden");
                hiddenField.setAttribute("name", key);
                hiddenField.setAttribute("value", params[key]);

                form.appendChild(hiddenField);
            }

            document.body.appendChild(form);
            form.submit();
        }
    </script>

我是这样称呼它的:

<a href="#" onclick="postToUrl('/account/add_to_blacklist/watched_user_id{{ message.recipient.user.id }}/next={{ request.get_full_path }}', {}, 'POST');">To blacklist</a>

这是我的观点:

class AddToBlacklistView(View):

    def post(self, request, watched_user_id, next_url=None, *args, **kwargs):
        if not next_url:
            next_url = '../profile.html/user_id{0}'.format(watched_user_id)
        if request.user.is_authenticated:
            try:
                user = User.objects.select_related("profile").get(username=request.user)
                watched_user = User.objects.select_related("profile").get(id=watched_user_id)
            except User.DoesNotExist:
                raise Http404
            if watched_user.id == user.id:
                return redirect(next_url)
            if watched_user not in user.profile.blacklist.all():
                user.profile.blacklist.add(watched_user)
                user.save()
            if watched_user.profile in user.profile.friends.all():
                user.profile.friends.remove(watched_user.profile)
                if user.profile in watched_user.profile.friends.all():
                    friendship = Friendship.objects.get(user=watched_user.profile, friend=user.profile)
                    if friendship.status != 3:
                        friendship.status = 2
                        friendship.save()
            if watched_user in user.profile.bookmarks.all():
                user.profile.bookmarks.remove(watched_user)
            return redirect(next_url)
        else:
            return redirect(next_url)

我试过了,但没用:

<meta name="csrf-token" content="{{ csrf_token }}">
<script>
    $.ajaxSetup({
        headers: {
            'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
        }
    });
</script>

我也尝试将其作为参数传递,但没有帮助:

csrfmiddlewaretoken: '{{ csrf_token }}' 

更新: 我还尝试为视图添加装饰器,但它继续抛出相同的错误:

from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_protect

    @method_decorator(csrf_protect)
    def post ...

我还在视图上尝试了 @method_decorator(ensure_csrf_cookie),该视图使用调用 Javascript 函数的 HTML 呈现页面,但我仍然收到 403 错误。

我也尝试了 https://docs.djangoproject.com/en/3.0/ref/csrf/ 中的这段代码,它继续抛出相同的 403 错误。

        function getCookie(name) {
            let cookieValue = null;
            if (document.cookie && document.cookie !== '') {
                const cookies = document.cookie.split(';');
                for (let i = 0; i < cookies.length; i++) {
                    const cookie = cookies[i].trim();
                    // Does this cookie string begin with the name we want?
                    if (cookie.substring(0, name.length + 1) === (name + '=')) {
                        cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                        break;
                    }
                }
            }
            return cookieValue;
        }

        const csrftoken = getCookie('csrftoken');

            function csrfSafeMethod(method) {
                // these HTTP methods do not require CSRF protection
                return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
            }
            $.ajaxSetup({
                beforeSend: function(xhr, settings) {
                    if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                        xhr.setRequestHeader("X-CSRFToken", csrftoken);
                    }
                }
            });

请帮帮我!

我在这里找到了解决方案: submitting a hyperlink by GET or POST

我不得不修改它,因为在我的页面上有一个人的列表,每个人都有一个菜单:

<form id="myform1_{{ message.recipient.user.id }}" method="post" action="/account/add_to_blacklist/watched_user_id{{ message.recipient.user.id }}/next={{ request.get_full_path }}" >
{% csrf_token %}

</form>
<a href="#" onclick="document.getElementById('myform1_{{ message.recipient.user.id }}').submit();">Add to blacklist</a>