zoukankan      html  css  js  c++  java
  • django自关联,auth模块

    一、自关联

    写蛮好的一篇博客:https://www.cnblogs.com/Kingfan1993/p/9936541.html
    

    1.一对多关联

    1.表内自关联是指表内数据相关联的对象和表是相同字段,这样我们就直接用表内关联将外键关联设置成自身表的字段

    2.例如,对于微博评论,每条评论都可能有子评论,但每条评论的字段内容应该都是相同的,并且每条评论都只有一个父评论,这就满足了一对多的情形,父评论id为关联字段,可以对应多个子评论

    3.外键关联是在子评论中,有关联字段的是子评论,子评论查父评论是正向,父评论查子评论是反向

    4.一对多的自关联可以应用在BBS论坛的留言功能中

    # models.py中
    
    # 文章表 
    """
    id     title         content
    1       'hello'		 'nihao....'
    2       'world'		 'shijie....'
    """
    class Article(models.Model):
    	title = models.CharField(max_length=32)
    	content = models.CharField(max_length=500)
    
    # 评论表
    """
    id  article_id  content   reply_id(自关联,作为外键关联自身表的主键id)     uid
    1   1			'cool'    0  (不是任何评论的回复)                      
    2	1	        'hehe'	  0
    3   1           'wtf'     1  (表示的是这条评论是回复id为1的评论)
    4   1           'how'     0
    5   2           'haha'    0
    6   1           'wow'     1  (也是回复的第一条评论)
    7   2           'Um'      5  (回复第五条评论)
    8   1           'aha'     3  (回复第三条评论)
    """
    class Comment(models.Model):
    	article = models.ForeignKey("Article")
    	content = models.CharField(max_length=255)
    	reply = models.ForeignKey("Comment", default=0)
    

    2.多对多关联

    1.例如,建立一张相亲对象表,里面有男有女,我们就可以通过自关联来建立多对多的关系

    2.通过ManyToManyField将外键关联自身的主键id

    # models.py中
    
    class User(models.Model):
    	name = models.CharField(max_length=32)
    	gender_list = [
    		(1, "男"),
    		(2, "女"),
    	]
    	gender = models.IntegerField(choices=gender_list,default=1)
    	r = models.ManyToManyField("User")
    

    3.通过python3 manage.py makemigrationspython3 manage.py migrate提交建表模型之后,会生成两个表,一个是主表,另一个是从表

    app_user表 和 app_user_r表
    

    4.从表中的的两个字段,一个是 from_主表名_id,一个是 to_主表名_id

    5.当我们通过 from_主表名_id 相关联的对象查与 to_主表名_id相关联的对象时,可以直接通过 '主表对象.关系表(从表)' 查询

    # views.py中
    
    # 查询和jojo的女生
    res = models.User.objects.filter(name='jojo', gender=1).first()
    #print(res)  # object
    objs = res.m.all()  
    for obj in objs:
    	print(obj.name)
    '''
    对应的SQL语句:
    1. select * from app01_user_m where from_user_id = 1;  
    得到的结果就是对应到app_user_r表中的数据时:to_user_id=[3,4] 所对应的对象
    
    2. select * from app01_user where id in (3,4);
    '''
    

    6.当我们 通过 to_主表名_id相关联的对象查 from_主表名_id 相关联的对象时,则需要通过 '主表对象.关系表_set' 进行查询

    # views.py中
    
    # 查询和 fanbingbing 约会的男生
    res = models.User.objects.filter(name='fanbingbing', gender=2).first()
    objs = res.user_set.all()
    for obj in objs:
    	print(obj.name)
    '''
    对应的SQL语句:
    1. select * from app01_user_m where to_user_id = 3; 
    得到的结果就是对应到app_user_r表中的数据时:from_user_id=[1,2] 所对应的对象
    
    2. select * from app01_user where id in (1,2); 
    '''		
    

    二、auth模块

    1.auth的简单使用

    1.执行数据库迁移的那两条命令时,即使我们没有建表,django是不是也会创建好多张表?我们创建之后去看一下里面的一个叫auth_user表,既然是表,那肯定应该有对应的操作改表的方法

    2.auth_user表的记录的添加:创建超级用户,不可以手动插入,因为密码是加密的,手动添加的明文密码没有意义

    3.我们可以在pycharm中使用导航栏中的Tools里的run manage.py Task 中输入createsuperuser

    # views.py 中
    
    # 就可以使用auth认证了,做一个简单的登陆
    
    from django.contrib import auth
    
    def test(request):
    
        if request.method == "GET":
            return render(request,"test.html")
        else:
            name = request.POST.get("user")
            psw = request.POST.get("psw")
    
            myuser = auth.authenticate(request,username=name,password=psw)  # 如果auth_user表中有这条记录,则返回一个user对象(一般就是用户名)
    
            if myuser: 
    
                auth.login(request,myuser)  # 会产生一个user对象,可以在任何视图函数中调用
                """
                给当前成功登陆的用户保存登陆状态,之前是通过cookie或者session,现在通过auth;
                request.session["name"] = name等价于:auth.login(request,myuser)
                """
                
                return HttpResponse("success")
            else:
                return redirect("/test/")
    
    # 在其他视图函数中演示
    def other(request):
        
        print(request.user)
        print(request.user.is_authenticated)
        
        return HttpResponse("ok")
    
    # 总结:
    # 1.只要登陆成功执行了auth.login(request,user)
    # 之后在其他任意的视图函数中都可以通过request.user获取当前登陆用户对象
    
    # 2.当没有执行auth.login,request.user打印出来的是匿名用户。将session表数据删除即可演示该效果
    
    # 3.如何判断request.user用户是否通过auth.login登陆呢?request.user.is_authenticated,打印:print(request.user.is_authenticated)
    
    # 为何执行auth.login之后,其他视图函数中就可以通过request.user拿到当前登陆对象呢?
    # django的中间件中有没有一个叫 'django.contrib.auth.middleware.AuthenticationMiddleware'的中间件,它干了件什么事,能不能推导一下?
    # 在web端取出session去django_session表里面查相应的数据
    

    4.注销

    auth.logout(request)
    # 等价于删除session数据request.session.flush()
    

    2.装饰器

    # 装饰器校验是否登陆及跳转
    
    from django.contrib.auth.decorators import login_required
    
    @login_required(login_url='/login/',redirect_field_name='old')  # 没登陆会跳转到login页面,并且后面会拼接上你上一次想访问的页面路径/login/?old=/my_view/,可以通过redirect_field_name参数修改next键名(如果不写这个参数,则为127.0.0.1:8090/login/?old=/my_view/,再无啥用了)
    def my_view(request):
      return HttpResponse("ok")
    

    如果我所有的视图函数都需要装饰并跳转到login页面,那么会很繁琐,我们可以在项目下的settings.py文件中进行配置

    # settings.py
    
    # 可以在配置文件中指定auth校验登陆不合法统一跳转到某个路径
    LOGIN_URL = '/login/'  # 既可以全局配置,也可以局部配置
    

    3.通过auth实现注册功能

    1.我们除了通过命令行输入,还可以通过auth提供的其他方法,对auth_user表进行数据的添加

    # app的views.py文件中
    
    from django.contrib.auth.models import User
    
    def register(request):
        if request.method == "GET":
            return render(request, "register.html")
        else:
        	user_name = request.POST.get("username")
        	psw = request.POST.get("psw")
        	
      		# User.objects.create()  # 不能用这个,因为密码是明文
    
    		User.objects.create_user(username=user_name,password=psw)  # 创建普通用户
    		# User.objects.create_superuser(username=user_name,password=psw,email=233@qq.com)  # 创建超级用户
    

    4.修改密码

    def modify(request):
    	if request.method=='GET':
    		return render(request, 'modify.html')
        else:
    		oldpsw = request.POST.get('oldpsw')
            newpsw = request.POST.get('newpsw')
    
            res = request.user.check_password(oldpsw) # 获取密码
            print(res)
            if res:
                request.user.set_password(newpsw)
                request.user.save()
                return HttpResponse('ok')
            else:
                return render(request, 'modify.html')
    

    5.自定义模型表应用auth功能

    1.扩张auth_user表

    2.一对一关联(不推荐)

    from django.contrib.auth.model s import User
    
    class UserDetail(models.Models):
    	phone_number = models.CharField(max_length=11)
    	user = models.OnoToOneField(to=User)
    

    3.面向对象的继承

    • 需要在项目下的settings.py文件中进行配置
    # settings.py中
    
    """
    1.指定我不再使用默认的auth_user表而是使用我自己创建的Userinfo表
    2.自定义认证系统默认使用的数据表之后,我们就可以像使用默认的auth_user表那样使用我们的UserInfo表了
    3.库里面也没有auth_user表了,原来auth表的操作方法,现在全部用自定义的表均可实现
    """
    
    # AUTH_USER_MODEL = "app名.models里面对应的模型表名"
    AUTH_USER_MODEL = "app01.User"
    
    • 就可以在app下的models.py文件中创建我们自己的用户信息表了
    # models.py中
    
    from django.contrib.auth.models import User,AbstractUser
    
    # 继承了auth中的user表
    class UserInfo(AbstractUser):
    	phone_number = models.CharField(max_length=32)
    

    6.总结

    	
    		1.auth登录
    			
    			obj = auth.authenticate(username, password)
    			
    			if obj:
    				auth.login(request, obj)
    				
    		2.业务逻辑函数验证:
    			
    			- request.user.is_authenticated()
    			
    			- from django.contrib.auth.decorators import login_required
    				@login_required()
    			
    		3.auth注册:
    			本质就是向auth_user表添加数据
    			
    			- createsuperuser
    			
    			- models.User.objects.create_user()   
    			- models.User.objects.create_superuser()   
    			
    		4.auth的密码更该:
    			
    			auth.checkpassword()  : 验证原来的密码是否正确
    			
    			auth.setpassword() : 设置新的密码
    			
    			auth.save()
    			
    		5.注销(登出)
    			
    			auth.logout(request)
    			
    			本质上就是删除django_session中所对应的的记录
    			
    		6.auth_user表的扩展:
    			
    			- onetoonefield
    			
    			- 继承子 AbstractUser 类
    
  • 相关阅读:
    python 并发编程 多线程 event
    python 并发编程 多线程 定时器
    python 并发编程 多线程 信号量
    linux top 查看CPU命令
    python 并发编程 多线程 GIL与多线程
    python 并发编程 多线程 死锁现象与递归锁
    python 并发编程 多线程 GIL与Lock
    python GIL全局解释器锁与互斥锁 目录
    python 并发编程 多线程 GIL全局解释器锁基本概念
    执行python程序 出现三部曲
  • 原文地址:https://www.cnblogs.com/pythonywy/p/11373769.html
Copyright © 2011-2022 走看看