17.用户登录2

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里

 

还有一种更好的登录实现方式,基于类的方法。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": "用户名或密码错误"})

你可能感兴趣的:(17.用户登录2)