• Python Day 66 Django框架、Auth认证模块、Auth模块常用方法、扩展默认的auth_user表、补充orm 模型类中releatename属性和 自关联


      ##Auth认证模块

    #Auth模块是什么?
    Auth模块是Django自带的用户认证模块:
    我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统。此时我们需要实现包括用户注册、用户登录、用户认证、注销、修改密码等功能,这还真是个麻烦的事情呢。
    Django作为一个完美主义者的终极框架,当然也会想到用户的这些痛点。它内置了强大的用户认证系统--auth,它默认使用 auth_user 表来存储用户数据。

      ##Auth模块常用方法

    #1、authenticate()
    提供了用户认证功能,即验证用户名以及密码是否正确,一般需要username 、password两个关键字参数。
    如果认证成功(用户名和密码正确有效),便会返回一个 User 对象。
    authenticate()会在该 User 对象上设置一个属性来标识后端已经认证了该用户,且该信息在后续的登录过程中是需要的。
    用法:
    user = authenticate(username='usernamer',password='password')
    
    
    #2、login(HttpRequest, user)
    
    该函数接受一个HttpRequest对象,以及一个经过认证的User对象。
    该函数实现一个用户登录的功能。它本质上会在后端为该用户生成相关session数据。
    用法:
    from django.contrib.auth import authenticate, login
       
    def my_view(request):
      username = request.POST['username']
      password = request.POST['password']
      user = authenticate(username=username, password=password)
      if user is not None:
        login(request, user)
        # Redirect to a success page.
        ...
      else:
        # Return an 'invalid login' error message.    
    #3、logout(request)
    该函数接受一个HttpRequest对象,无返回值。
    当调用该函数时,当前请求的session信息会全部清除。该用户即使没有登录,使用该函数也不会报错。
    用法:
    from django.contrib.auth import logout
       
    def logout_view(request):
      logout(request)
      # Redirect to a success page.
     # 等价于删除session数据request.session.flush() 
    #4、is_authenticated()
    用来判断当前请求是否通过了认证。
    用法:
    def my_view(request):
      if not request.user.is_authenticated():
        return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
    
    #5、login_requierd()
    auth 给我们提供的一个装饰器工具,用来快捷的给某个视图添加登录校验。
    用法:
    from django.contrib.auth.decorators import login_required
          
    @login_required
    def my_view(request):
      ...
    
    若用户没有登录,则会跳转到django默认的 登录URL '/accounts/login/ ' 并传递当前访问url的绝对路径 (登陆成功后,会重定向到该路径)。
    如果需要自定义登录的URL,则需要在settings.py文件中通过LOGIN_URL进行修改。
    示例:
    LOGIN_URL = '/login/'  # 这里配置成你项目登录页面的路由
    
    #6、create_user()
    auth 提供的一个创建新用户的方法,需要提供必要参数(username、password)等。
    用法:
    from django.contrib.auth.models import User
    user = User.objects.create_user(username='用户名',password='密码',email='邮箱',...)
    
    #7、create_superuser()
    auth 提供的一个创建新的超级用户的方法,需要提供必要参数(username、password)等。
    用法:
    from django.contrib.auth.models import User
    user = User.objects.create_superuser(username='用户名',password='密码',email='邮箱',...)
    
    #8、check_password(password)
    auth 提供的一个检查密码是否正确的方法,需要提供当前请求用户的密码。
    密码正确返回True,否则返回False。
    用法:
    ok = user.check_password('密码')
    
    #9、set_password(password)
    auth 提供的一个修改密码的方法,接收 要设置的新密码 作为参数。
    注意:设置完一定要调用用户对象的save方法!!!
    用法:
    user.set_password(password='')
    user.save()
    
    #10、User对象的属性
    User对象属性:username, password
    is_staff : 用户是否拥有网站的管理权限.
    is_active : 是否允许用户登录, 设置为 False,可以在不删除用户的前提下禁止用户登录。
    - 登陆
        
    from django.contrib import auth
    
    user_obj =  auth.authenticate(request, username=username, password=pwd)
    ## authenticate: 主要是从auth——user这张表中查询比较 数据, 返回一个user_obj对象
    # 类似于user=models.User.objects.filter(username=name,password=pwd).first()
    if user_obj:
        ####设置session
        auth.login(request, user=user_obj)
        作用:
            1. 设置cookie, session
            2. 生成request.user的对象, 这个对象可以再视图函数中使用 
            3. request.user这个对象  相当于 request.session
    
    - 验证
    
     is_login = request.user.is_authenticated()  ###判断用户是否登录, is_login 是一个bool值
     
     装饰器判断:
        from django.contrib.auth.decorators import login_required
    
        @login_required(login_url='/login/')
        def index2(request):
           return HttpResponse('index2')
    
    全局配置跳转地址:
        
        LOGIN_URL = "/login/"
        
        @login_required
        def index3(request):
            return HttpResponse('index3')
    
    
    - 注册
    
    from django.contrib.auth.models import User
    def register(request):
        if  request.method == 'GET':
            return render(request, 'register.html')
        else:
            username = request.POST.get('username')
            pwd = request.POST.get('pwd')
    
            # User.objects.create(username=username, password=pwd)
            User.objects.create_superuser(username=username, password=pwd,  email='111@qq.com')
            User.objects.create_user(username=username, password=pwd)
    
            return HttpResponse('successs')
                    
    
    - 修改密码
    def modify(request):
        if request.method == 'GET':
            return render(request, 'modify.html')
        else:
    
            old_pwd = request.POST.get('old_pwd')
    
            res = request.user.check_password(old_pwd)  ### 检测老密码
            if res:
                new_pwd = request.POST.get('new_pwd')
                request.user.set_password(new_pwd)   ### 设置新密码
                request.user.save()    #### 保存
    
                return HttpResponse('ok')
    
    
    
    - 安全退出
    
    def logout(request):
    
        auth.logout(request)
        return HttpResponse('安全退出')
    Auth认证使用案例

      ##扩展默认的auth_user表

    这内置的认证系统这么好用,但是auth_user表字段都是固定的那几个,我在项目中没法拿来直接使用啊!
    比如,我想要加一个存储用户手机号的字段,怎么办?
    聪明的你可能会想到新建另外一张表然后通过一对一和内置的auth_user表关联,这样虽然能满足要求但是有没有更好的实现方式呢?
    答案是当然有了。
    我们可以通过继承内置的 AbstractUser 类,来定义一个自己的Model类。
    这样既能根据项目需求灵活的设计用户表,又能使用Django强大的认证系统了。
    
    - 一对一关联(不推荐)
    
      ```python
      from django.contrib.auth.models import User
      
      class UserDetail(models.Models):
        phone = models.CharField(max_length=11)
        user = models.OnoToOneField(to=User)
      ```
    
    - 面向对象的继承    
    
        from django.contrib.auth.models import AbstractUser
        class UserInfo(AbstractUser):
            """
            用户信息表
            """
            nid = models.AutoField(primary_key=True)
            phone = models.CharField(max_length=11, null=True, unique=True)
        
            def __str__(self):
                return self.username
    注意:
    按上面的方式扩展了内置的auth_user表之后,一定要在settings.py中告诉Django,我现在使用我新定义的UserInfo表来做用户认证。写法如下:
        AUTH_USER_MODEL = "app名.models里面对应的模型表名"
    
    再次注意:
    一旦我们指定了新的认证系统所使用的表,我们就需要重新在数据库中创建该表,而不能继续使用原来默认的auth_user表了。

       ##补充orm 模型类中releatename属性和 自关联

    ########################## 补充orm
    from app01 import models
    def test110(request):
    
        ##################### 1、一对多 关系   #############
        #### 正向查询
        # res = models.UserInfo.objects.filter(username='小猴').first()
        # print(res.ut.title)
    
        ### 反向查询
        ### 传统方式: 表明小写_set.all()
        # res = models.UserType.objects.filter(id=2).first()
        # print(res.userinfo_set.all())
    
        ### 现代方式: releate_name = 'xxx'
        # res = models.UserType.objects.filter(id=2).first()
        # print(res.users.all())
    
    
        ###############  多对多 #############
        ### 查询和gouyang相亲的女孩子
        ### 创传统方式:表名小写_set
        # res = models.Boy.objects.filter(name='gouyang').first()
        # b2g = res.boy2girl_set.all()
        # for obj in b2g:
        #     print(obj.g.name)
    
        ### 现代方式:
        # res = models.Boy.objects.filter(name='gouyang').first()
        # b2g = res.xxx.all()
        # for obj in b2g:
        #     print(obj.g.name)
    
    
    
        ### 补充增加boy2girl
        # models.Boy2Girl.objects.create(b_id=1, g_id=4)
        #
        # boy_obj = models.Boy.objects.filter(name='gouyang').first()
        # girl_obj = models.Girl.objects.filter(name='秀琴').first()
        # models.Boy2Girl.objects.create(b=boy_obj, g=girl_obj)
    
    
        ##################### 上面补充的releatename
    
    
        ####################2、 自关联 ############
    
        ####### 自己写第三张表
        ### 和勾洋约会的女生
        # res = models.User.objects.filter(name='罗文', gender=1).first()
        # objs = res.xxx.all()  #### select * from app01_u2u where b_id=2
        # print(objs)
        #
        # for obj in objs:
        #     print(obj.g.name)
    
        ### 和蓉蓉约会的男生
        # res = models.User.objects.filter(name='蓉蓉', gender=2).first()
        # objs = res.yyy.all()
        # for obj in objs:
        #     print(obj.b.name)
    
    
        ###### 不写第三张表
        ### 我定义的规则:
        ### from_user_id : 男生id
        ### to_user_id : 女生id
    
        ### 和罗文约会的女生
        res = models.User.objects.filter(name='罗文', gender=1).first()
        objs = res.m.all()
        '''
            1. seelct * from app01_user_m where  from_user_id=2 ## to_user_id:[5,6]
            2. select * from app01_user where id in [5,6] #### 所有相亲女生的名字
        '''
        for obj in objs:
            print(obj.name)
    
        #### 和品如约会的男生;
        res = models.User.objects.filter(name='品如', gender=2).first()
        objs = res.user_set.all()
    
        '''
            1. seelct * from app01_user_m where  to_user_id=6 ## from_user_id:[1,2] 
            2. select * from app01_user where id in [1,2]
        '''
    
    ###################3、一对多自关联:
    news:
        id   content
    
    comment:
        
        id     news_id      content      reply_id
    
        1        1           别逼逼        null
        2        1           就逼逼        null
        3        1           瞎比比        null
        4        2           xxxxxx        null
        5        1           kkkkkk         2
        6        1           llllll         1
        
    显示:
        第一条新闻:
        
            - 别逼逼
                - llllll
            
            - 就逼逼
                - kkkkkk
            - 瞎比比
        
        
        第二条新闻:
            - xxxxxx  
    
    
    
    #################4、补充添加数据的另一种方式(直接对象,默认会把对象里面的id放到相应的表中):
                models.Boy2Girl.objects.create(b_id=1, g_id=4)
    
                boy_obj = models.Boy.objects.filter(name='gouyang').first()
                girl_obj = models.Girl.objects.filter(name='秀琴').first()
                models.Boy2Girl.objects.create(b=boy_obj, g=girl_obj)
  • 相关阅读:
    springboot 时间戳和 数据库时间相差14个小时
    财富的起源读书笔记1
    高性能mysql读书笔记1
    springboot项目使用 apollo 配置中心
    MongoDB图形化管理工具
    oracle体系结构详解
    三、oracle 体系结构
    用DOS批处理实现FTP自动上传、下载、清理文件
    ORA-01033:ORACLE initialization or shutdown in progress
    从WEB SERVICE 上返回大数据量的DATASET
  • 原文地址:https://www.cnblogs.com/liangzhenghong/p/11214045.html
Copyright © 2020-2023  润新知