django登录、登出和使用限制

用户登录、登出、登录限制

 

1、在app01/models.py里面定义User模型,通过AbstractBaseUser扩展用户模型

from django.db import models
from django.contrib.auth.models import   BaseUserManager, AbstractBaseUser, PermissionsMixin
from django.contrib.auth import get_user_model

class UserManager(BaseUserManager):
    def _create_user(self , telephone, username, password, **kwargs):
        if not telephone:
            raise  ValueError("必须要传递手机号码!")
        if not password:
            raise  ValueError("必须要传递密码")
        user = self.model( telephone = telephone, username= username , **kwargs)
        user.set_password( password )
        user.save()
        return  user

    def create_user(self,  telephone, username, password, **kwargs):
        kwargs['is_superuser'] = False
        return self._create_user( telephone = telephone, username=username, password = password, **kwargs )

    def create_superuser(self, telephone, username, password, **kwargs):
        kwargs['is_superuser'] = True
        return  self._create_user( telephone = telephone, username=username, password = password, **kwargs )

class User(AbstractBaseUser, PermissionsMixin):
    telephone = models.CharField(max_length=11, unique=True)
    email = models.CharField(max_length=100, unique=True)
    username = models.CharField(max_length=100)
    is_active = models.BooleanField(default=True)

    USERNAME_FIELD = "telephone"   #USERNAME_FIELD作用,是执行authenticate验证, username参数传入后,实际校验的是telephone字段
    REQUIRED_FIELDS = []

    objects = UserManager()

    def get_full_name(self):
        return self.username

    def get_short_name(self):
        return self.username

class Article(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    # author = models.ForeignKey(  User, on_delete= models.CASCADE )
    #get_user_model()会自动获取settings.py里面 AUTH_USER_MODEL,这样不管你定义的那个User,都可以自动获取,更安全
    author = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)

2、在settings.py设置用户模型用哪个

AUTH_USER_MODEL = "app01.User"

3、在 app01/forms.py里面定义表达,用于验证提交的数据

错误说明:


from django import forms
from django.contrib.auth import  get_user_model

class LoginForm(forms.ModelForm):
    remember = forms.IntegerField( required= False)
    class Meta:
        model = get_user_model()
        fields = ['telephone', 'password']


#将telephone写在fields当中,因为telephone在User模型有Unique唯一约束,所以每次提交form表单,from会对有唯一性约束的模型字段自动进行校验

#如果检测到数据库已经有对应的数据,就代表提交重复,会报下面错误:
November 08, 2019 - 10:28:46
Django version 2.0.13, using settings 'untitled1108.settings'
Starting development server at http://127.0.0.1:8080/
Quit the server with CTRL-BREAK.
[08/Nov/2019 10:28:48] "GET /test/ HTTP/1.1" 200 30
[08/Nov/2019 10:28:57] "GET /login/ HTTP/1.1" 200 989
提交的数据为:
<QueryDict: {'csrfmiddlewaretoken': ['uX31VMCh50kLLTeIrFbluEbCXcahchHnVzWHoCpG60A6ap5LeACKkaPmAT487RNn'], 'telephone': ['15555655555'], 'password': ['555555']}>
<ul class="errorlist"><li>telephone<ul class="errorlist"><li>User with this Telephone already exists.</li></ul></li></ul>
[08/Nov/2019 10:29:02] "POST /login/ HTTP/1.1" 302 0
[08/Nov/2019 10:29:02] "GET /login/ HTTP/1.1" 200 989

所以,正确的写法如下:

from django import forms
from django.contrib.auth import  get_user_model

class LoginForm(forms.ModelForm):
    remember = forms.IntegerField( required= False)
    telephone = forms.CharField(max_length=11)
    class Meta:
        model = get_user_model()
        # fields = ['telephone', 'password']
        fields = [ 'password',]

 

4、配置模板,用于登录

4.1在settings.py里面配置模板路径

默认的路径 DIRS是空的
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [  ],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

app01/ templates配置如下, 而工程下的templates一般用于放公用模板base.html,共其他应用模板继承;或者,放一些公用的errors.html;

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [   os.path.join(BASE_DIR, 'templates'),
                    os.path.join(BASE_DIR, 'app01/templates'), ],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

5、创建 app01/templates/login.html如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="" method="POST">
        <input type="hidden" name="csrfmiddlewaretoken" value="{{csrf_token}}">
        <table>
            <tr>
                <td> 用户号码:</td>
                <td>  <input type="text" name="telephone">  </td>
            </tr>
            <tr>
                <td> 密码:</td>
                <td>  <input type="password" name="password"> </td>
            </tr>
            <tr>
                <td>
                    <label for="">
                        记住我
                        <input type="checkbox" name="remember" value="1">
                    </label>
                </td>
            </tr>
            <tr>
                <td></td>
                <td> <input type="submit" value="登录"> </td>
            </tr>
        </table>
    </form>
</body>
</html>

 

 

6、在视图里调用User模型,进行登录、登出、登录限制

from django.shortcuts import render, HttpResponse, reverse,redirect
from django.db import  connection
from app01.models import User
from django.contrib.auth import  authenticate, login, logout
from django.contrib.auth.decorators import login_required
from app01.forms import LoginForm


def test(request):
    #创建用户
    # User.objects.create_user( telephone="15555655555", password="555555", username="zhiliao5" )

    #用认证
    user = authenticate(request, username="15555655555", password="555555")
    if user:
        print(user.username)
        print("验证成功!")
    else:
        print("验证失败!")
    return  HttpResponse("继承AbstractUser扩展用户")


def my_login(request):

    if request.method == "GET":
        return render(request, "login.html")
    else:
        print("提交的数据为:"); print(request.POST)
        form = LoginForm(request.POST)
        if form.is_valid():
            telephone = form.cleaned_data.get("telephone")
            password = form.cleaned_data.get("password")
            remember = form.cleaned_data.get("remember")
            user = authenticate(request, username =telephone, password=password)
            if user and user.is_active:
                login(request, user)
                if remember:
                    request.session.set_expiry(None)
                else:
                    request.session.set_expiry(0)
                return HttpResponse("登录成功!")
            else:
                return  HttpResponse("手机号码或者密码错误!")
        else:
            print(form.errors)
            return redirect( reverse("login") )

def my_logout(request):
    logout(request)
    return HttpResponse("成功退出")

@login_required(login_url="/login/")
def profile(request):
    return HttpResponse("这是个人中心,只有登录了以后才能查看到!")

7、在urls.py里面定义路由

from django.contrib import admin
from django.urls import path
from app01 import views as app01_views

urlpatterns = [
    path('admin/', admin.site.urls),
    path("test/", app01_views.test),
    path("login/", app01_views.my_login, name = "login"),
    path("logout/", app01_views.my_logout, name = "logout"),
    path("profile/", app01_views.profile, name="profile"),
]

 

8、登录,无 “记住我” 功能, 登录成功后,关闭浏览器,session就过期

 

 

9、登录,带  “记住我” 的功能, 登录成功后,session过期时间为两个星期

 

 

 

 

10、登出后, session的创建时间和过期时间相等,等于session无效

 

 

 

11、登录限制,目前直接访问http://127.0.0.1:8080/profile, 若是没有登录的状态,会跳转到登录的url  

    

 

 登录成功后没跳转到 /profile/界面,因为代码里面只是return HttpResponse, 因为没有告诉django跳转的路径

需要跳转的优化代码如下:

from django.shortcuts import render, HttpResponse, reverse,redirect
from django.db import  connection
from app01.models import User
from django.contrib.auth import  authenticate, login, logout
from django.contrib.auth.decorators import login_required
from app01.forms import LoginForm


def test(request):
    #创建用户
    # User.objects.create_user( telephone="15555655555", password="555555", username="zhiliao5" )

    #用认证
    user = authenticate(request, username="15555655555", password="555555")
    if user:
        print(user.username)
        print("验证成功!")
    else:
        print("验证失败!")
    return  HttpResponse("继承AbstractUser扩展用户")


def my_login(request):

    if request.method == "GET":
        return render(request, "login.html")
    else:
        print("提交的数据为:"); print(request.POST)
        form = LoginForm(request.POST)
        if form.is_valid():
            telephone = form.cleaned_data.get("telephone")
            password = form.cleaned_data.get("password")
            remember = form.cleaned_data.get("remember")
            user = authenticate(request, username =telephone, password=password)
            if user and user.is_active:
                login(request, user)
                if remember:
                    request.session.set_expiry(None)
                else:
                    request.session.set_expiry(0)

                #判断是否有next跳转的URL
                next_url = request.GET.get("next")
                if next_url:
                    return  redirect( next_url)

                return HttpResponse("登录成功!")
            else:
                return  HttpResponse("手机号码或者密码错误!")
        else:
            print(form.errors)
            return redirect( reverse("login") )

def my_logout(request):
    logout(request)
    return HttpResponse("成功退出")

@login_required(login_url="/login/")
def profile(request):
    return HttpResponse("这是个人中心,只有登录了以后才能查看到!")

跳转以后的效果如下:

 

 

 

 

 

 

 

 

 

 

posted on 2019-11-07 13:24  芦苇草鱼  阅读(1064)  评论(1编辑  收藏  举报