zoukankan      html  css  js  c++  java
  • 166.登录、退出登录以及登录限制案例

    权限和分组

    登录、注销和登录限制

    1. 登录

    在使用authenticate进行验证后,如果验证通过了,那么就会返回一个user对象,拿到user对象之后,可以使用django.contrib.auth.login进行登录,部分示例代码如下:
    user = authenticate(username=username, password=password)
    if user is not None and user.is_active:
        login(request, user)
    

    2. 注销:

    注销、或者是退出登录,我们可以通过django.contrib.auth.logout来实现,它会调用flush()方法清除掉用户的session数据。部分示例代码如下:
    from django.contrib.auth import logout
    
    def logout_view(request):
        logout(request)
        return HttpResponse('Success!')
    

    3. 登录限制:

    有时间,某个视图函数是需要经过登录才能访问的,那么我们就可以通过django.contrib.auth.decorators.login_required装饰器实现。示例代码如下:
    from django.contrib.auth.decorators import login_required
    
    <!--可以指定登录的url-->
    @login_required(login_url='/login_logout/')
    def profile(request):
        return HttpResponse('个人中心!')
    

    项目完整代码如下

    (1)views.py文件中示例代码如下:

    from django.http import HttpResponse
    from djang.shortcuts import render, redirect, reverse
    from .models import User
    from .forms import login_logout_Form
    from django.contrib.auth import authenticate, auth
    from django.views import View
    
    
    <!--1.首先定义一个添加用户信息的视图-->
    def addview(request):
        <!--1. 添加普通用户-->
        user = User.objects.create_user(username='孤烟逐云', telephone='18833331111', password='111111')
        user.email = 'ant@qq.com'
        user.save()
        return HttpResponse('successful!')
        
        <!--2. 添加超级用户-->
        user = User.objects.create_superuser(username='云中云', telephone='18833332222', password='111111')
        user.email = 'ant01@qq.com'
        user.save()
        return HttpResponse('success!')
     
    
    <!--表单的形式提交用户数据-->
    <!--2. 之后定义一个首页类视图,如果是get请求,返回 一个模板;如果是post请求就采用表单验证提交的数据的合法性,如果合法就添加到数据库中-->
    class login_logout(View):
    
        def get(self, request):
            return render(request, 'login_logout.html')
            
        def post(self, request):
            form = login_logout_Form(request.POST)
            if form.is_valid():
                telephone = form.clean_data.get('telephone')
                password = form.clean_data.get('password')
                remember = form.clean_data.get('remember')
                user = authenticate(request, username=telephone, password=password)
                <!--如果验证成功就会返回一个user对象,验证不成功,就返回None-->
                if user and user.is_active:
                    login(request, user)
                    if remember:
                        <!--设置过期时间通过session.set_expiry(),设置为None的话,就会使用全局的-->
                        request.session.set_expiry(None)
                    else:
                        request.session.set_expiry(0)
                    return HttpResponse('登录成功!')
                else:
                    return HttpResponse('用户名或密码不正确!')
            <!--如果表单没有验证成功-->
            else:
                print(form.errors.get_json_data())
                return redirect(reverse('login_logout:login_logout'))       
    

    (2)forms.py文件中示例代码如下:

    from django import forms
    from .models import User
    from django.contrib.auth import get_user_model
    
    class login_logout_Form(forms.ModelForm):
        remember = forms.IntegerField(required=False)
        class Meta:
            model = get_user_model()
            fields = ['telephone', 'password']
        <!--如果你想要验证模型User中定义的所有字段, 就可以指定fields = '__all__'-->
    

    (3)在urls.py文件中进行视图函数与url之间的映射。需要注意的是,一定要将类转换为类视图,即调用as_view()转换,示例代码如下:

    from django.urls import path
    from . import views
    
    
    app_name = 'login_logout'
    
    
    urlpatterns = [
        path('', views.login_logout.as_view(), name='login_logout'),
        path('add/', views.addview, name='add')
    ]
    
    (1)否者的话,就会出现TypeError: init() takes 1 positional argument but 2 were given.
    (2)并且需要注意的是,在调用Django内置的验证方法authenticate()验证的时候,第一个参数一定要传入request。

    (4)这里使用的User模型,是我们通过继承AbstractBaseUser重写的User模型,对模型的字段进行了大幅度的改动,示例代码如下:

    from django.db import models
    from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager
    from django.contrib.auth.models import AbstractUser
    from django.contrib.auth import get_user_model
    from django.contrib.auth import authenticate
    
    
    class UserManager(BaseUserManager):
        def _create_user_(self, telephone, username, password, **kwargs):
            if not telephone:
                raise ValueError('请输入密码!')
            if not username:
                raise ValueError('请输入用户名!')
    
            # 注意,这里是self.model代表的是当前的User模型而不能写self.User()因为UserManager没有这个属性
            user = self.model(telephone=telephone, username=username)
            user.set_password(password)
            user.save()
            return user
    
        def create_user(self, telephone, username, password, **kwargs):
            kwargs['is_super'] = False
            return self._create_user_(telephone=telephone, username=username, password=password, **kwargs)
    
        def create_superuser(self, telephone, username, password, **kwargs):
            kwargs['is_super'] = True
            return self._create_user_(telephone=telephone, username=username, password=password, **kwargs)
    
    
    # PermissionsMixin: 是定义用户时定义用户权限,必须继承
    # AbstractBaseUser:User的基类其中涉及的字段最少,如果先定义自己的User模型,
    # 将大部分Django中默认的字段删除的话,就可以继承该类
    # AbstractBaseUser类中定义的字段有:password,last_login,is_active,is_super
    class User(AbstractBaseUser, PermissionsMixin):
        # 必须设置的两个字段username,email
        username = models.CharField(max_length=100)
        email = models.EmailField(unique=True)
        telephone = models.CharField(max_length=11, unique=True)
    
        is_active = models.BooleanField(default=True)
    
        # 唯一性验证设置为telephone
        USERNAME_FIELD = 'telephone'
        # REQUIRED_FIELDS为空的列表代表的是,在验证用户登录的时候只需要输入password和USERNAME_FIELD指定的字段就行了
        # 如果还想在验证用户的时候输入其他的字段,那么就可以将该字段设置在该列表中。
        REQUIRED_FIELDS = []
    
        # 以上自定义的User模型上并没有objects方法,所以我们需要自定义
        objects = UserManager()
    
        def get_full_name(self):
            return self.username
    
        def get_short_name(self):
            return self.username
    
    

    (5)如果使用这种继承AbstractBaseUser的方式进行重写Django内置的User模型的话,就需要告诉Django,现在要使用的是自己定义的User模型,这就需要在settings.py文件中配置:

    AUTH_USER_MODEL = 'login_Logout.User'
    

    (6)views.py文件中涉及的模板login_logout.html中的实例代码如下:

    <form action="" method="post">
    {% csrf_token %}
        <table>
            <tbody>
            <tr>
                <td>手机号:</td>
                <td><input type="text" name="telephone"></td>
            </tr>
            <tr>
                <td>密码:</td>
                <td><input type="text" name="password"></td>
            </tr>
            <tr>
                <td>
                    <label for="">
                        <input type="checkbox" name="remember" value="1">
                    </label>
                </td>
                <td></td>
            </tr>
            <tr>
                <td></td>
                <td><input type="submit" value="提交"></td>
            </tr>
            </tbody>
        </table>
    </form>
    
    需要注意的是,如果你在提交表单信息的时候没有加上{% csrf_token %}或者是,就会出现403的csrf禁止页面,所以可以选择一种方式进行添加。
    之后就可以输入url进行登录验证了,这时会在pycharm终端打印出错误信息:{'telephone': [{'message': 'User with this Telephone already exists.', 'code': 'unique'}]}。因为在models.py文件中的模型User中定义的telephone字段就是唯一的,即unique=True,而且在forms文件中继承了User所有的字段,所以此时在验证的fields中指定telephone的话,就会验证数据库中的telephone的唯一性。
    解决办法就是在forms.py文件的验证字段fields中不要指定telephone,可以重新定义一个字段telephone,示例代码如下:
    class Login_logout_Form(forms.ModelForm):
        remember = forms.IntegerField(required=False)
        telephone = forms.CharField(max_length=11)
        class Meta:
            model = get_user_model()
            fields = ['password']
    
    此时,再次在浏览器中的表单中输入用户的信息telephone和password就可以登录成功了。

    (7)定义个人中心的视图,示例代码如下:

    def profile(request):
        return HttpResponse('个人中心!')
    

    在子urls.py文件中进行一层视图函数与url之间的映射,示例代码如下:

    path('profile/', views.profile, name='profile'),
    

    (8)此时,用户登录与否我们都可以通过url访问个人中心页面,这个有些不符合情理,我们可以将个人中心页面定义为只有用户登录之后,才能访问。

    from django.contrib.auth.decorators import login_required
    <!--login_required是一个定义好的装饰器-->
    
    <!--装饰器中的login_url指定登录页面的url-->
    @login_required(login_url='/login_logout/')
    def profile(request):
        return HttpResponse('个人中心!')
    
    此时,我们如果在没有登录的情况下,去访问个人中心页面,就会跳转到登录页面url,http://127.0.0.1:8000/login_logout/?next=/login_logout/profile/, 登录之后就会重定向到个人中心页面。

    (9)定义退出登录的视图logout_view,示例代码如下:

    from django.contrib.auth import logout
    
    def logout_view(request):
    <!--logout()函数会将session中记录的sessionid清空,其实调用的就是flush()方法,sessionid的到期时间也会变为浏览器关闭就到期-->
        logout(request)
        return HttpResponse("退出登录!")
    
    始于才华,忠于颜值;每件事情在成功之前,看起来都是天方夜谭。一无所有,就是无所不能。
  • 相关阅读:
    20145305 《信息安全系统设计基础》第10周学习总结
    20145305 《信息安全系统设计基础》实验五 网络通信
    20145305 《信息安全系统设计基础》实验四 驱动程序设计
    20145304 《信息安全系统设计基础》课程总结
    20145304 《信息安全系统设计基础》第十四周学习总结
    计算机系统要素
    20145304 《信息安全系统设计基础》第十三周学习总结
    20145304 《信息安全系统设计基础》第十二周学习总结
    GDB调试汇编堆栈
    20145304 20145315 《信息安全系统设计基础》 实验五 网络通信
  • 原文地址:https://www.cnblogs.com/guyan-2020/p/12350008.html
Copyright © 2011-2022 走看看