##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_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)