zoukankan      html  css  js  c++  java
  • Django之auth模块

    auth模块是Django内置的用户权限管理模块:比如用户的创建,认证,登入,注销等。当我们创建一个APP时,auth模块就会自动添加在 INSTALLED_APPS=['django.contrib.auth',]

    auth常用的几个方法:

      User模型(auth/models.py中):用来维护用户信息的模型;比如用户的创建,认证等; 源码中User模型继承自AbstractUser,而AbstractUser继承自AbstractBaseUser,有以下字段:

        username: 最长150个字符,必须传递

        first_name:外国人的第一个名字

        last_name: 外国人的最后一个名字

        email: 邮箱

        is_staff: 是否为员工,可以进入后台管理系统

        is_active: 是否是可用的。对于一些想要删除账号的数据,我们设置这个值为False就可以了,而不是真正的从数据库中删除。

        date_joined: 账号创建的时间。

        objects = UserManager():  定义objes方法(两个方法一个是创建普通用户:create_user()和创建一个超级用户create_superuser())

        EMAIL_FIELD = "email"

        USERNAME_FIELD = "username"  唯一验证身份的标志

        REQUIRED_FIELDS = ["email"]

        而AbstractBaseUser中的字段有:(它中的字段和方法对于User和AbstractUser都可以用)

        password :密码,经过哈希处理的

        last_login:最后登入时间

        is_active = True :默认账号是可用状态

        常用的几个方法:

        get_username() :返回用户名

        save():保存

        set_password():设置密码

        check_password():检验密码是否正确

        User模型的基本使用方法:

          使用User模型之前我们需要先把模型映射的数据库中即(makemigrations,migrate),数据库中的auth_user表就是保存用户信息的。

          上代码: 

    from django.shortcuts import render,HttpResponse
    from django.contrib.auth.models import User
    from django.contrib.auth import authenticate
    def index(request):
        User.objects.create_user("李四","zhangsan@163.com","123456")   #创建一个普通用户,参数可以只传递一个用户名,其他的可传可不传
        User.objects.create_superuser("里斯","lisi@163.com","111111")   #创建一个超级用户,三个参数用户名,邮箱,密码必须传递
        user = User.objects.first()  
        user.set_password("qweqwe")  #修改密码,修改之后必须保存
        user.save()
        user = authenticate(request,username = "李四",password = "123456")  #验证这个用户存不存在,如果存在返回这个用户的用户名
        if user:
            print("有这个用户")
        else:
            print("没有这个用户")
        return HttpResponse("ok")

        User模型虽然已经很强大了,但是有时依然不能满足我们的需求,比如我们想再定义几个字段,或者添加一些方法什么的,这个时候我们就需要扩展User模型,方法有以下四种:

        User模型的扩展一之proxy模型:

          使用范围:我们对它的字段很满意了没有其他可以添加,只是需要再添加一些方法,比如想获取所有的超级管理员;

          注意:这种方式只能添加方法,不能添加字段,除了添加的这个方法之外和User没有区别

          app/models.py中的代码:

    from django.contrib.auth.models import User
    
    class getsuperuser(User):  #定义一个类继承自User类
        class Meta:
            proxy = True   #设置代理模式
        @classmethod
        def get_superuser(cls):   #定义一个类方法(获取所有的管理员)
            return cls.objects.filter(is_superuser=True)

          app/views.py中的代码:

    from django.shortcuts import render,HttpResponse
    from django.contrib.auth.models import User
    from .models import getsuperuser  #导入这个模块
    
    userlist = getsuperuser.get_superuser()   #获取所有的管理
        for user in userlist:
            print(user)
    
    userlist01 = User.objects.all()
        print(userlist01)
    userlist02 = getsuperuser.objects.all()    #在这种代理模式中User模型和代理模型的使用是一样的即Uer.objects.all()等价于getsuperuser.objects.all()
        print(userlist02)
    return HttpResponse("ok")

        User模型的扩展二之一对一外键:(这种方式是创建一个新的表,用来保存一些新的字段并且和User表一一对应)

          使用范围:如果我们要添加一个字段和方法

          app/models.py中的代码:

    from django.db import models
    from django.contrib.auth.models import User
    from django.dispatch import receiver
    from django.db.models.signals import post_save
    
    class UserExtension(models.Model):    #定义一个User一对一的外键类
        user = models.OneToOneField(User,on_delete=models.CASCADE,related_name="extension")  #外键User
        telephone = models.CharField(max_length=11,unique=True)
        school = models.CharField(max_length=100)
    @receiver(post_save,sender = User)    #定义一个信号机制,信号的发送者sender是User,信号是post_save,当User这个实例被创建的时候同时创建一个user的外键,否则保存这个实例和外键
    def handle_user_extenson(sender,instance,created,**kwargs):
        if created:         //如果User被创建了,那么同时创建一个UserExtension,并且外键与User对应
            UserExtension.objects.create(user=instance)
        else:
            instance.extension.save()    //如果User被保存,则UserExtension也保存

        app/views.py中代码:

     user = User.objects.create_user("王二","wanger@163.com","123123")  #创建一个用户
        user.extension.telephone = "18899998888"  #给这个用户添加手机号
        user.extension.school = "北京交通大学"     #给这里用户添加一个学校
        user.save()

        User模型的扩展三之继承自AbstractUser:

          使用范围:如果我们不想改变原来User的内容,又想在数据库中的同一个表中添加一些新的字段

          User本身也是继承这个AbstractUser模型写的,相当于我们在原User的基础上重新写了User

          因为objects这个方法也在这个User模型中,所以我们可以重新定义objects;

          注意:(1)这种方式破坏了User数据表的结构,所以必须在第一次migrate之前定义好(2)在setting中设置:AUTH_USER_MODEL = 'front.User'(这里的front是你的app)

          app/models.py中的代码

    rom django.db import models
    from django.contrib.auth.models import User
    from django.contrib.auth.models import AbstractUser,AbstractBaseUser,BaseUserManager
    
    
    class UserManager(BaseUserManager):  #重新定义一个UserManager
        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(AbstractUser):
        telephone = models.CharField(max_length=11,unique=True)
        school = models.CharField(max_length=100)
    
    #指定telephone作为USERNAME_FIELD,以后使用authenticate;函数验证的时候,就可以根据telephone来验证;而不是原来的username
        USERNAME_FIELD = 'telephone'
        REQUIRED_FIELDS = []
      objects = UserManager() # 重新定义Manager对象,在创建user的时候使用telephone,username和password,而不是使用username和password

        app中views.py中的代码

    from django.shortcuts import render,HttpResponse
    from django.contrib.auth import authenticate
    from .models import User  #这里需要导入的是models下面的User(注意)
    def index(request):
        telephone = '18899996666'
        password = '111111'
        username = '张三'
        User.objects.create_superuser(telephone=telephone,username=username,password=password)
        user = authenticate(request,username = "18899996666",password = "111111")  #这里的username并不是真正的username而是代表USERNAME_FIELD的值,使用手机号验证,返回的是一个手机号
        print(user)    //返回的是一个手机号
       print(user.username) //返回的是一个用户名
    return HttpResponse("ok")

        User模型的扩展四之继承自AbstractBaseUser:(这时其实就相当于在写一个AbstractUser)

        使用范围:如果既想改变验证方式,又想添加字段,还不想要User原来的字段,可以完全重新写一个User;继承自AbstractBaseUser

        注意(和上面一样):(1)这种方式破坏了User数据表的结构,所以必须在第一次migrate之前定义好(2)在setting中设置:AUTH_USER_MODEL = 'front.User'(这里的front是你的app)

        app/models.py中的代码

    from django.db import models
    from django.contrib.auth.models import User
    from django.contrib.auth.models import AbstractUser,AbstractBaseUser,BaseUserManager,PermissionsMixin
    
    
    class UserManager(BaseUserManager):  #和上面一样重新定义了bjects
        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):  #定义User继承在AbstractBaseUser,PermissionsMixin(其实这时相当于在写一个AbstractUser)
        telephone = models.CharField(max_length=11,unique=True)
        username = models.CharField(max_length=10,unique=True)
    
    
        USERNAME_FIELD = "telephone"
        REQUIRED_FIELDS = []
    
        objects = UserManager()
    
        def get_full_name(self):
            return self.username
    
        def get_short_name(self):
            return self.username

         app/views.py中的代码:

    from django.shortcuts import render,HttpResponse
    from django.contrib.auth import authenticate
    from .models import User
    def index(request):
        telephone = '18899996666'
        password = '111111'
        username = '张三'
        User.objects.create_superuser(telephone=telephone,username=username,password=password)
        user = authenticate(request,telephone = "18899996666",password = "111111")
        print(user)
        return HttpResponse("ok")

      login/logout模块和登入限制:

    from django.shortcuts import render,HttpResponse,redirect,reverse
    from django.contrib.auth import authenticate,login,logout
    from .models import User
    from .forms import LoginForm
    from django.contrib.auth.decorators import login_required
    
    
    def my_login(request):    //登入
        if request.method == "GET":   //如果是get请求则返回登入页面
            return render(request,"login.html")
        if request.method == "POST":    //如果是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,telephone=telephone,password=password)  //验证
                if user and user.is_active:
                    login(request,user)  //登入
                    if remember:    //设置session
                        request.session.set_expiry(None)
                    else:
                        request.session.set_expiry(0)
                    next_url = request.GET.get("next")  //如果有next,则直接跳转到这个页面(限制登入时django自动添加了next参数)
                    if next_url:
                        return redirect(next_url)
                    else:
                        return HttpResponse("登入成功")
                else:
                    return HttpResponse("用户名或者密码错误")
            else:
                print(form.errors.get_json_data())
                return redirect(reverse("login"))
    
    def my_logout(request):
        logout(request)  //退出登入
        return HttpResponse("退出成功")
    
    @login_required(login_url="/login/")  //限制登入装饰器,login_url表示失败后去哪个页面
    def my_file(request):
        return HttpResponse("个人中心")

    form.py

    from django import forms
    from django.contrib.auth import get_user_model  //获取User模型(这个方法是或者setting中的AUTH_USER_MODEL = "login.User"class LoginForm(forms.ModelForm):
        remember = forms.BooleanField(required=False)
        telephone = forms.CharField(max_length=11)
        class Meta:
            model = get_user_model()
            fields = ["password"]  //这里不能添加telephone,因为Model.Form会把这个手机号去数据库中验证,如果有直接报错,所以telephone自己定义一个
            error_messages={
                "telephone":{
                    "required":"手机号必须有"
                },
                "password":{
                    "required": "手机号必须有"
                }
            }

      权限

        添加权限两种方式第一种是模型中添加权限:

    class Article(models.Model):
        author = models.ForeignKey(get_user_model(),on_delete=models.CASCADE)
        title = models.CharField(max_length=20)
        content = models.CharField(max_length=100)
    
        class Meta:
            permissions = [
                ("black_article","拉黑文章")
            ]

      第二种方式代码中添加权限:

    def add_permissions(request):
        content_type = ContentType.objects.get_for_model(Article)
        Permission.objects.create(name="可编辑的权限",codename="edit_article",content_type=content_type)
        return HttpResponse("添加成功")

       User模型和模型权限之间的管理

    def operate_permissions(request):
        user = User.objects.first()
        content_type = ContentType.objects.get_for_model(Article)   //
        print(content_type.id)
        permissions = Permission.objects.filter(content_type=content_type)   //获取这个模型所有的权限
        for permission in permissions:
            print(permission)
        # user.user_permissions.set(permissions)  #一次性添加多个权限
        # user.user_permissions.clear()   #一次性清楚所有权限
        user.user_permissions.add(permissions[0],permissions[1])  //一次添加一个权限
        user.user_permissions.add(*permissions)
        user.user_permissions.remove(permissions[1])   //一次移除一个权限
        if user.has_perm("login.aa_article"):   //检查一次是否拥有某个权限,格式是app_name.codename
            print("有这个权限")
        permissions_all = user.get_all_permissions()   //获取user所有的权限
        print(permissions_all)
        return HttpResponse("添加成功")

       权限装饰器(规定必须拥有什么样的权限才能访问视图函数)

    from django.contrib.auth.decorators import permission_required  //导入装饰器,这个装饰器做了两件事(一件事验证是否登入,另一件事验证是否有权限)
    
    @permission_required("login.add_article",login_url="/login/",raise_exception=True)  //规定只有add_article的权限才能访问这个视图函数也可以是一个列表["login.add_article","login.view_article"];login_url表示没有权限的时候跳转的页面,raise_exception=True表示没有权限的时候跳转到403页面
    def add_article(request):
       
        return HttpResponse("添加文章的页面")

       权限分组:

    def operate_group(request):
        # group = Group.objects.create(name="财务")  #添加一个分组
        # content_type = ContentType.objects.get_for_model(Article)
        # permissions = Permission.objects.filter(content_type=content_type)  //获得这个模型的所有权限
        group = Group.objects.filter(name="财务").first()  //获得第一个分组
        # group.permissions.set(permissions)   //给这个分组添加权限
        # group.save()  //保存
        user = User.objects.first()
        # user.groups.add(group)  //把这个user添加到这个组
        # user.save()
        # permissions = user.get_group_permissions()  //获得所在组的所有权限
        # print(permissions)
        if user.has_perm("login.add_article"):
            print("有这个权限")
        #has_perm(),先去判断user里面有没有这个权限,如果没有再去所在分组中查找
        return HttpResponse("分组")

      模板中使用权限:有一些页面只想展示给有权限的人看,比如有关财务的页面只给具有财务权限的人看。

      #因为setting.TEMPLATS.OPTIONS.context_processors下添加了django.contrib.auth.context_processors.auth上下文处理器,所以在模板中可以直接通过perms来获取用户的所有权限
    {% if perms.login.add_article %} <p>添加文章</p> {% endif %}

     

  • 相关阅读:
    过拟合问题详解
    C++数据结构原理和经典问题求解--绪论
    centos系统 anaconda3(python3)安装pygrib
    pycharm激活教程
    如何查看电脑是几核几线程(网传方法有错误)
    深度学习过程
    VS2010 编译 boost thread库
    windows多线程编程
    matplotlib画条形图
    matplotlib画折线图,并以时间作为横轴
  • 原文地址:https://www.cnblogs.com/yan-peng/p/10147222.html
Copyright © 2011-2022 走看看