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

 

posted on 2019-07-19 16:26  Icon-Liang  阅读(186)  评论(0编辑  收藏  举报