csrf token for ajax in django2

China☆狼群 提交于 2019-12-14 03:58:21

问题


I am learning Django2,and try to make a login page with csrf_token and ajax.

I hope that if user hasn't lgoin,that will turn to the login page and send a variable next as a tag of the page before login.If user login successfully that I can turn to the homepage or page marked by next.

I read the docs of Django2, and try to code like below,however,when I click "LOGIN" button,it just refresh the login page and get no error

I am confused and have no idea already.Please help.

login views:

def login(request):
    if request.is_ajax():
        uf = UserForm(request.POST)
        if uf.is_valid():
            # get info from form
            username = uf.cleaned_data['username']
            password = uf.cleaned_data['password']
            user = auth.authenticate(request, username=username, password=password)
            if user is not None:  # user match
                auth.login(request, user)
                if request.GET.get('next'):
                    next_url = request.GET.get('next')
                    return JsonResponse({'redirect_url': next_url})
                    # return redirect(request.GET.get('next'))
                else:
                    return JsonResponse({'redirect_url': 'home'})
            else:  # user not match
                error_msg = ["username or pwd mistake"]
                return JsonResponse({'error_msg': error_msg})
    else:
        uf = UserForm()
    return render(request, 'login.html', {'uf': uf})

html :

    <form>
      {% csrf_token %}
       {{ uf.username }}
       {{ uf.password }}
      <div id="errorMsg"></div>
        <button type="submit" class="btn btn-default" id="loginButton">login</button>
     <input type="hidden" name="next" id="redirect-next" value="{{ next|escape }}"/>
   </form>

JQuery:

       $("#loginButton").click(function () {
    $.ajax({
        url: "",
        type: 'POST',
        dataType: "json",
        data: {username: $("#inputEmail3").val(), password: $("#inputPassword3").val()},
        beforeSend: function (xhr, settings) {
            var csrftoken = Cookies.get('csrftoken');
            function csrfSafeMethod(method) {
                // these HTTP methods do not require CSRF protection
                return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
            }
            if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                xhr.setRequestHeader("X-CSRFToken", csrftoken);
            }
        },
        success: function (result) {
            if (result.error_msg) {
                $('#errorMsg').show().text('user info error') //print an alert on the page
            }
            else {
                location.href = result.redirect_url //turn to homepage or page before login
            }
        }
    })
});

回答1:


You don't need to take effort to write a login view of your own like this. Django provides easier methods to implement it.

First make sure the following are included in your settings.py

MIDDLEWARE_CLASSES = [
    ...
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    ...
]
INSTALLED_APPS = [
    ...
    'django.contrib.auth',
    'django.contrib.contenttypes',
    ...
]

Add all the login URLs to your main urls.py:

from django.urls import path
from django.conf.urls import include


urlpatterns = [
....
    path('accounts/', include('django.contrib.auth.urls')),
....
]

Don't forget to run python manage.py migrate to create the tables required for the auth app. Now that the app and URLs are ready, templates need to be created. All the templates for the app should be placed under a folder named registration under your templates directory. The directory structure should be something like.

your_django_app/
    templates/
        registration/
            login.html
    __init__.py
    apps.py
    settings.py
    urls.py
    views.py
    wsgi.py

The contents of the login.html should be something like:

<form id="loginform" action="{% url 'login' %}" method="POST">
{% csrf_token %}
{% if next %}
    <input type="hidden" name="next" value="{{ next }}" />
{% endif %}
    <input name="username" id="id_username" type="text">
    <label>Username</label>
    <input name="password" id="id_password" type="password">
    <label>Password</label>
{% if form.errors %}
    Error! Wrong credentials.
{% endif %}
    <button type="submit">Login</button>
</form>

After this include these in your settings.py file for redirecting users correctly after login.

LOGIN_REDIRECT_URL = '/'
LOGIN_URL = '/accounts/login'

You are all set to go. Make sure to create at least one user before trying this out by running python manage.py createsuperuser. For all pages that require users to login before viewing them you can use the @login_required decorator above their respective view functions to redirect them to the login page before showing the page. Example:

from django.shortcuts import render
from django.contrib.auth.decorators import login_required

@login_required
def home(request):
    return render(request, 'home/index.html')



回答2:


Here there is a short and simple way to parse the csrf_token using ajax:

Inside the script tag.

    $.ajax({
           url: window.location.pathname,
           type: 'POST',
           data: {
                 ......,
                // Note this step.
                'csrfmiddlewaretoken': "{{ csrf_token }}"
                },
                success: function() {
                   .....
                }
    });

Hope things work well as I have used this thing to parse the csrf_token in my 2 Django based projects. Cheers!




回答3:


This might be related to this issue

As your button tries to submit the form but you want it to be handled handled by the script.

try changing the button type to

type="button" 


来源:https://stackoverflow.com/questions/51145914/csrf-token-for-ajax-in-django2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!