问题
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