views.py還需要修改,authenticate的參數需要寫名字,且響應函數不能和系統默認名相同。
from django.shortcuts import render
from django.contrib.auth import authenticate, login
# Create your views here.
def user_login(request):
if request.method == "POST":
user_name = request.POST.get("username","")
pass_word = request.POST.get("password","")
user = authenticate(username=user_name, password=pass_word)
if user is not None:
login(request,user)
return render(request,"index.html")
else:
return render(request,"login.html",{})
elif request.method == "GET":
return render(request, "login.html", {})
urls.py里的響應函數名也要改。然后就可以登陸了。然后如果想要郵箱和用戶名都能登錄,需要自定義 authenticate的功能。先在settings.py里AUTHENTICATION_BACKENDS = (
'apps.users.views.CustomerBackend',
)
在views里:
from django.shortcuts import render
from django.contrib.auth import authenticate, login
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q
from users.models import UserProfile
class CustomerBackend(ModelBackend):
def authenticate(self, username=None, password=None, **kwargs):
try:
user = UserProfile.objects.get(Q(username=username)|Q(email = username))
if user.check_password(password):
return user
except Exception as e:
return None
# Create your views here.
def user_login(request):
if request.method == "POST":
user_name = request.POST.get("username","")
pass_word = request.POST.get("password","")
user = authenticate(username=user_name, password=pass_word)
if user is not None:
login(request,user)
return render(request,"index.html")
else:
return render(request,"login.html",{})
elif request.method == "GET":
return render(request, "login.html", {})
創建一個類繼承ModelBackend類,在里面可以自定義authenticate方法,它就是下邊響應函數中的authenticate,現在可以自定義這個函數了。userprofile繼承了AbstractUser類,可以直接調用里面的方法user.check_password。因為不能直接對比輸入密碼和數據庫里的密碼,一個是明文一個不是,要用這個方法檢查。雖然只是創建了類CustomerBackend,但打開網頁可以發現程序運行進入了這個類的邏輯里。Q這個方法支持并集和且的關系。get(Q(username=username)|Q(email = username))意思是輸入的用戶名等于數據庫里的username可以,等于email也可以。
再增加個功能,在用戶輸入錯誤的賬戶密碼時提示錯誤.把響應函數里的else部分寫成
return render(request,"login.html",{"msg":"用戶名或密碼錯誤"})
然后把這個msg寫在login.html里
</div>
<div class="error btns login-form-tips" id="jsLoginTips">{{ msg }}</div>
<div class="auto-box marb38">
還有一種更好的登錄實現方式,基于類的方法。views.py里
from django.shortcuts import render
from django.contrib.auth import authenticate, login
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q
from django.views.generic.base import View
from users.models import UserProfile
class CustomerBackend(ModelBackend):
def authenticate(self, username=None, password=None, **kwargs):
try:
user = UserProfile.objects.get(Q(username=username)|Q(email = username))
if user.check_password(password):
return user
except Exception as e:
return None
class LoginView(View): #這樣就不用做POST和GET的判斷了,django根據情況自己調用
def get(self,request):
return render(request, "login.html", {})
def post(self,request):
user_name = request.POST.get("username", "")
pass_word = request.POST.get("password", "")
user = authenticate(username=user_name, password=pass_word)
if user is not None:
login(request, user)
return render(request, "index.html")
else:
return render(request, "login.html", {"msg": "用戶名或密碼錯誤"})
urls里
from django.conf.urls import url
from django.contrib import admin
from django.views.generic import TemplateView
from users.views import LoginView
import xadmin
from apps.users.views import login
urlpatterns = [
url(r'^xadmin/', xadmin.site.urls),
url('^$', TemplateView.as_view(template_name="index.html"),name="index"),
url('^login/$', LoginView.as_view(),name="login") #as_view()方法判斷是post還是get然后返回響應函數名
]
as_view()方法判斷是post還是get然后返回響應函數名。
form可以對前端表單傳遞到后端的數據是否滿足要求,滿足要求再進入邏輯。現在users里創建forms.py:
from django import forms
class LoginForm(forms.Form):
username = forms.CharField(required=True)
password = forms.CharField(required=True,min_length=5)
需要和前端html文件里表單的變量名相同,否則不能檢驗。
views.py里LoginView類改為
from .forms import LoginForm
class LoginView(View): #這樣就不用做POST和GET的判斷了,django根據情況自己調用
def get(self,request):
return render(request, "login.html", {})
def post(self,request):
login_form = LoginForm(request.POST) #前端的html文件中變量名必須和forms里定義的兩個名字相同才能自動檢查
if login_form.is_valid(): #is_valid檢查login_form的error是否為空,為空則滿足條件
user_name = request.POST.get("username", "")
pass_word = request.POST.get("password", "")
user = authenticate(username=user_name, password=pass_word)
if user is not None:
login(request, user)
return render(request, "index.html")
else:
return render(request, "login.html", {"msg": "用戶名或密碼錯誤"})