zoukankan      html  css  js  c++  java
  • Django 之认证模块

    1. 内容回顾

        1. form表单
            1. form表单能做的事儿:
                1. 帮你生成HTML(form表单中获取用户输入的标签)
                2. 帮你做数据有效性的校验,汇总错误信息
                3. 保持用户之前输入的数据
            2. 用法
                1. 创建一个form类
                    from django import forms
                    class RegForm(forms.Form):
                        username = forms.Charfield(...)
                        
                2. 使用RegForm类
                    1. 模板中使用:
                        生成一个form_obj对象  form_obj = RegForm()
                        1. {{ form_obj.as_p }}
                        
                        2. form_obj.username
                    2. 后端中使用:
                        生成一个form_obj对象  form_obj = RegForm(request.POST)
                        
                        form_obj.is_valid()     ---> 帮我们做校验的方法
                        
                            form_obj.cleaned_data  --> 获取经过校验的数据
            3. 常用的字段和参数
            4. 自定义校验规则
                1. 正则表达式
                    from django.core.validators import RegexValidator
                    
                    phone = forms.CharField(
                        ...
                        validators=[RegexValidator(r'^1[356789][0-9]{9}$', "手机格式不正确"), ]
                    )
                2. 自定义函数
                    from django.core.exceptions import ValidationError
                    
                    username = forms.CharField(
                        ...
                        validators=[zhangzhao, ...]
                    )
                
                3. 局部钩子
                    def clean_字段名(self):
                        # 1. 一旦不符合我订的校验规则,要抛出ValidationError
                        # 2. 符合校验规则 的话 一定一定一定要value返回
                        
                4. 全局的钩子
                    def clean(self):
                        self.cleaned_data  ---> 经过前面每个字段独立校验的所有符合要求的数据
                        self.add_error("字段名", "错误提示信息")
                        # 1. 一旦不符合我订的校验规则,要抛出ValidationError
                        
                        # 2. 符合校验规则 的话 一定一定一定要cleaned_data返回
        
    View Code

    1. Django 内置的认证系统

    1,auth模块

    https://www.cnblogs.com/liwenzhou/p/9030211.html

     

    1. from django.contrib import auth

    # 验证用户名和密码是否正确

    1,authenticate()   

    提供了用户认证,即验证用户名以及密码是否正确,一般需要username  password两个关键字参数

    如果认证信息有效,会返回一个  User  对象。authenticate()会在User 对象上设置一个属性标识那种认证后端认证了该用户,且该信息在后面的登录过程中是需要的。当我们试图登陆一个从数据库中直接取出来不经过authenticate()的User对象会报错的!!

    user_obj = auth.authenticate(username=username, password=pwd)

    # 调用内置的登录方法

    auth.login(request, user_obj)

    2,login(HttpRequest, user)

    该函数接受一个HttpRequest对象,以及一个认证了的User对象

    此函数使用django的session框架给某个已认证的用户附加上session id等信息。

    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.
        ...

    3logout(request) 注销用户

    from django.contrib.auth import logout
      
    def logout_view(request):
      logout(request)
      # Redirect to a success page.

    该函数接受一个HttpRequest对象,无返回值。当调用该函数时,当前请求的session信息会全部清除。该用户即使没有登录,使用该函数也不会报错。

    ,4user对象的 is_authenticated()

    要求:

    1  用户登陆后才能访问某些页面,

    2  如果用户没有登录就访问该页面的话直接跳到登录页面

    3  用户在跳转的登陆界面中完成登陆后,自动访问跳转到之前访问的地址

    方法1:

    def my_view(request):
      if not request.user.is_authenticated():
        return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))

    方法2:

    django已经为我们设计好了一个用于此种情况的装饰器:login_requierd()

    from django.contrib.auth.decorators import login_required
         
    @login_required
    def my_view(request):
      ...

    若用户没有登录,则会跳转到django默认的 登录URL '/accounts/login/ ' (这个值可以在settings.py文件中通过LOGIN_URL进行修改)。并传递  当前访问url的绝对路径 (登陆成功后,会重定向到该路径)。

    User对象

              User 对象属性:username, password(必填项)password用哈希算法保存到数据库

    is_staff : 用户是否拥有网站的管理权限.

    is_active : 是否允许用户登录, 设置为``False``,可以不用删除用户来禁止 用户登录

    1,is_authenticated()

    如果是真正的 User 对象,返回值恒为 True 。 用于检查用户是否已经通过了认证。

    通过认证并不意味着用户拥有任何权限,这个方法甚至也不检查该用户是否处于激活状态,只是表明用户成功的通过了认证。

    这个方法很重要, 在后台用request.user.is_authenticated()判断用户是否已经登录,如果true则可以向前台展示request.user.name

    2. 内置的auth使用的ORM 类(使用 create_user 创建用户)

    from django.contrib.auth.models import User

    User.objects.create_user()

    3. 检查密码是否正确check_password(passwd)

    用户需要修改密码的时候,首先要让其输入原来的密码 ,如果给定的值通过了密码检查,返回 True

    user_obj.check_password(原密码)

    4.  user_obj.set_password(新密码)

    修改密码: set_password()

    user = User.objects.get(username='')
    user.set_password(password='')
    user.save()

    user_obj.save()  !!!一定记得修改完要保存!!!

    修改密码实例:

    @login_required
    def set_password(request):
        user = request.user
        err_msg = ''
        if request.method == 'POST':
            old_password = request.POST.get('old_password', '')
            new_password = request.POST.get('new_password', '')
            repeat_password = request.POST.get('repeat_password', '')
            # 检查旧密码是否正确
            if user.check_password(old_password):
                if not new_password:
                    err_msg = '新密码不能为空'
                elif new_password != repeat_password:
                    err_msg = '两次密码不一致'
                else:
                    user.set_password(new_password)
                    user.save()
                    return redirect("/login/")
            else:
                err_msg = '原密码输入错误'
        content = {
            'err_msg': err_msg,
        }
        return render(request, 'set_password.html', content)
    View Code

    进阶

    这内置的auth_user表这么好用,但是我在项目中没法直接使用啊!比如,我想要加一个存储用户手机号的字段,怎么办?

    聪明的你可能会想到新建另外一张表然后通过一对一和内置的auth_user表关联,这样虽然能满足要求但是有没有更好的实现方式呢?

    答案是当然有了。

    我们可以通过继承内置的auth_user表的对应的类,来定义一个自己的ORM类。

    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表来做用户认证。写法如下:

    # 引用Django自带的User表,继承使用时需要设置
    AUTH_USER_MODEL = "app名.UserInfo"

    全部实例:

    views

    登录

    def login(request):
    
        if request.method == "POST":
    
            username = request.POST.get("username")
    
            pwd = request.POST.get("pwd")
    
            # 校验用户名、密码对不对
    
            user = auth.authenticate(username=username, password=pwd)
    
            if user:
    
                # 内置的login方法
    
                # 1. 生成Session数据,存一下user_id 然后把sessionid写入Cookie
    
                # 后续每一次请求来的时候,AuthenticationMiddleware中的process_request方法中
    
                # 会取到user_id,进而取到user对象,然后添加到request.user属性中 --> request.user = user
    
                # 后续我们都可以通过request.user拿到当前的登陆用户对象
    
                auth.login(request, user)
    
                return redirect("/home/")
    
     
    
        return render(request, "login.html")
    View Code 

    注册

     
    
    def reg(request):
    
        if request.method == "POST":
    
            username = request.POST.get("username")
    
            pwd = request.POST.get("pwd")
    
            # 创建用户
    
            # User.objects.create(username=username, password=pwd)
    
            # 调用内置的创建普通用户的专用方法,创建一个新的用户
    
            User.objects.create_user(username=username, password=pwd)
    
     
    
        return render(request, "reg.html")
    View Code

    跳转的

    @login_required
    
    def home(request):
    
        return render(request, "home.html")

    注销

    def logout(request):
    
        # 调用auth内置的注销方法
    
        auth.logout(request)
    
        return redirect("/login/")

    修改密码

    @login_required
    
    def set_password(request):
    
        if request.method == "POST":
    
            old_pwd = request.POST.get("old_pwd")
    
            pwd = request.POST.get("pwd")
    
            re_pwd = request.POST.get("re_pwd")
    
            # 先校验原密码对不对
    
            user_obj = request.user
    
            if user_obj.check_password(old_pwd):
    
                if pwd == re_pwd:
    
                    # 去数据库修改密码
    
                    user_obj.set_password(pwd)
    
                    # 修改密码一定要保存
    
                    user_obj.save()
    
                    return HttpResponse("修改成功")
    
            else:
    
                return HttpResponse("原密码错误")
    
     
    
        return render(request, "set_password.html")
    View Code

    Url

    urlpatterns = [
    
        url(r'^admin/', admin.site.urls),
    
        url(r'^login/', views.login),
    
        url(r'^reg/', views.reg),
    
        url(r'^home/', views.home),
    
        url(r'^logout/', views.logout),
    
        url(r'^set_password/', views.set_password),
    
    ]

    Html

    <h1>欢迎注册</h1>
    
    <form action="/reg/" method="post">
    
          {% csrf_token %}
    
        <input type="text" name="username">
    
        <input type="password" name="pwd">
    
        <input type="submit" value="注册">
    
    </form>
    
     
    
    <h1>欢迎登陆</h1>
    
    <form action="" method="post">
    
        {% csrf_token %}
    
        <input type="text" name="username">
    
        <input type="password" name="pwd">
    
        <input type="submit" value="登录">
    
    </form>
    
     
    
    <h1>Hello, {{ request.user.username }}</h1>
    
     
    
    <a href="/logout/">注销</a>
    
    <a href="/set_password/">修改密码</a>
    
     
    
    <form action="" method="post">
    
        {% csrf_token %}
    
        <p>原密码:<input type="password" name="old_pwd"></p>
    
        <p>新密码:<input type="password" name="pwd"></p>
    
        <p>重复密码:<input type="password" name="re_pwd"></p>
    
        <p><input type="submit" value="修改"></p>
    
    </form>
    
     
    四个页面

    2. BBS项目需求分析

    BBS项目表结构分析

    1. 用户表

    2. 文章

    3. 评论表

    - 评论文章

    - 评论别人的文章

    4. 标签

    5. 分类

    6. 点赞/反对

    - 一个用户只能点赞一次

    7. 博客站点表

    - 博客站点的标题

    - 博客的样式(自定制主题)

    3. 今日任务

    1. 昨天注册的页面集合今天学到的auth写一个完整的注册,使用扩展的UserInfo表

    2. 修改密码成功之后跳转到一个提示页面,5秒钟后跳转到登陆页面

    3. 在修改密码页面弹出一个弹窗提示修改成功,继续跳转回登录页面

    答案等等等

  • 相关阅读:
    微博个人中心效果
    微博弹性按钮
    ios9 3dtouch 博客
    去掉导航栏阴影
    模态全屏模式,实现半透明效果
    剪切图片
    修改push动画的方向
    数据库链接池终于搞对了,直接从100ms到3ms
    如何在Java代码中去掉烦人的“!=null”
    面试官:请讲下接口具体怎么优化!
  • 原文地址:https://www.cnblogs.com/maojiang/p/9243767.html
Copyright © 2011-2022 走看看