写蛮好的一篇博客:https://www.cnblogs.com/Kingfan1993/p/9936541.html
1.表内自关联是指表内数据相关联的对象和表是相同字段,这样咱们就直接用表内关联将外键关联设置成自身表的字段html
2.例如,对于微博评论,每条评论均可能有子评论,但每条评论的字段内容应该都是相同的,而且每条评论都只有一个父评论,这就知足了一对多的情形,父评论id为关联字段,能够对应多个子评论python
3.外键关联是在子评论中,有关联字段的是子评论,子评论查父评论是正向,父评论查子评论是反向web
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)
1.例如,创建一张相亲对象表,里面有男有女,咱们就能够经过自关联来创建多对多的关系django
2.经过ManyToManyField将外键关联自身的主键idcookie
# 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 makemigrations
和python3 manage.py migrate
提交建表模型以后,会生成两个表,一个是主表,另外一个是从表session
app_user表 和 app_user_r表
4.从表中的的两个字段,一个是 from_主表名_id,一个是 to_主表名_idapp
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' 进行查询ui
# 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); '''
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()
# 装饰器校验是否登录及跳转 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/' # 既能够全局配置,也能够局部配置
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) # 建立超级用户
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')
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中 """ 1.指定我再也不使用默认的auth_user表而是使用我本身建立的Userinfo表 2.自定义认证系统默认使用的数据表以后,咱们就能够像使用默认的auth_user表那样使用咱们的UserInfo表了 3.库里面也没有auth_user表了,原来auth表的操做方法,如今所有用自定义的表都可实现 """ # AUTH_USER_MODEL = "app名.models里面对应的模型表名" AUTH_USER_MODEL = "app01.User"
# models.py中 from django.contrib.auth.models import User,AbstractUser # 继承了auth中的user表 class UserInfo(AbstractUser): phone_number = models.CharField(max_length=32)
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 类