zoukankan      html  css  js  c++  java
  • 09 Django组件之用户认证组件

    没有学习Django认证组件之前使用装饰器方法

    from django.shortcuts import render, HttpResponse, redirect
    from app01.MyForms import EmpForm
    from app01 import models
    
    
    # Create your views here.
    
    def login_required(func):
        def inner(request, *args, **kwargs):
            if request.session.get("is_login"):
                ret = func(request, *args, **kwargs)
                return ret
            else:
                path = request.path
                print(path)
                return redirect("/login/?next=%s" % path)
        return inner
    
    
    def login(request):
        if request.method == "POST":
            form = EmpForm(request.POST)
            if form.is_valid():
                print(1111,form.cleaned_data)
                emp_obj = models.Emp.objects.filter(name=form.cleaned_data.get('name'),
                                          age=form.cleaned_data.get('age'),
                                          salary=form.cleaned_data.get('salary')).first()
                if emp_obj:
                    request.session['is_login'] = True
                    path = request.GET.get('next') or "/index/"
                    return redirect(path)
    
            else:
                clear_errors = form.errors.get("__all__")  # 获取全局钩子错误信息
                return render(request, "login.html", {"form": form, "clear_errors": clear_errors})
        else:
            form = EmpForm()
            return render(request, "login.html", {"form": form})
    
    
    
    @login_required
    def index(request):
        return HttpResponse("这是主页。。。")
    
    
    @login_required
    def order(request):
        return HttpResponse("这是订单。。。")
    
    
    def logout(request):
        request.session.flush()
        return redirect("/login/")
    app01/views.py
    from django import forms
    from django.core.exceptions import ValidationError  #导包  from django.core.exceptions import ValidationError
    from app01 import models
    
    class EmpForm(forms.Form):
        name = forms.CharField(min_length=5, label="姓名", error_messages={"required": "该字段不能为空!",
                                                                         "min_length": "用户名太短。"})
        age = forms.IntegerField(label="年龄")
        salary = forms.DecimalField(max_digits=5, decimal_places=2, label="工资")
        r_salary = forms.DecimalField(max_digits=5, decimal_places=2, label="请确认工资")
        # 局部钩子
        def clean_name(self):  # 名称不能随便起,必须要clean_类属性名称
            val = self.cleaned_data.get("name")
    
            if val.isdigit():
                raise ValidationError("用户名不能全是数字。")
            # elif models.Emp.objects.filter(name=val):
            #     raise ValidationError("用户名已存在。")
            else:
                return val
    
        def clean(self):
            salary = self.cleaned_data.get("salary")
            r_salary = self.cleaned_data.get("r_salary")
            if salary != r_salary:
                raise ValidationError("工资输入有误。")
            else:
                return self.cleaned_data
    app01/MyForms.py
    from django.db import models
    
    class Emp(models.Model):
        name = models.CharField(max_length=32)
        age = models.IntegerField()
        salary = models.DecimalField(max_digits=8, decimal_places=2)
    app01/models.py
    from django.contrib import admin
    from django.urls import path
    from app01 import views
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('login/', views.login),
        path('index/', views.index),
        path('order/', views.order),
        path('logout/', views.logout),
    ]
    urls.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
    <form action="" method="post" novalidate>
        {% csrf_token %}
        <div>
            <label for="id_{{ form.name.name }}">姓名</label>
            {{ form.name }} <span>{{ form.name.errors.0 }}</span>
        </div>
        <div>
            <label for="id_{{ form.age.name }}">年龄</label>
            {{ form.age }} <span>{{ form.age.errors.0 }}</span>
        </div>
        <div>
            <label for="id_salary">工资</label>
            {{ form.salary }} <span>{{ form.salary.errors.0 }}{{ clear_errors.0 }}</span>
        </div>
        <div>
            <label for="id_r_salary">请再输入工资</label>
            {{ form.r_salary }} <span>{{ form.r_salary.errors.0 }}{{ clear_errors.0 }}</span>
        </div>
        <input type="submit">
    
    </form>
    <a href="/logout/">注销</a>
    
    </body>
    </html>
    login.html

    一、auth模块

    1
    from django.contrib import auth

    django.contrib.auth中提供了许多方法,这里主要介绍其中的三个:

    1.1 、authenticate()   

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

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

    1
    user = authenticate(username='someone',password='somepassword')

    1.2 、login(HttpRequest, user)  

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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.
        ...

    1.3 、logout(request) 注销用户  

    1
    2
    3
    4
    5
    from django.contrib.auth import logout
       
    def logout_view(request):
      logout(request)
      # Redirect to a success page.

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

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
    <h3>用户登录</h3>
    <form action="" method="post">
        {% csrf_token %}
        <p>用户名:<input type="text" name="user"></p>
        <p>密码:<input type="password" name="pwd"></p>
        <input type="submit">
    </form>
    <a href="/auth_logout/">注销</a>
    </body>
    </html>
    login1.html--auth模块使用
    from django.shortcuts import render, HttpResponse, redirect
    from app01.MyForms import EmpForm
    from app01 import models
    from django.contrib import auth
    from django.contrib.auth.decorators import login_required  #auth自带的装饰器
    # Create your views here.
    
    @login_required
    def index(request):
        return HttpResponse("这是主页。。。")
    
    @login_required
    def order(request):
        return HttpResponse("这是订单。。。")
    
    
    def logout(request):
        request.session.flush()
        return redirect("/login/")
    
    
    def auth_login(request):
        if request.method == "POST":
            user = request.POST.get("user")
            pwd = request.POST.get("pwd")
            user_obj = auth.authenticate(username=user, password=pwd)  # 过滤合法用户。有则返回该对象,无,返回None
            print(user_obj, type(user_obj))
            print(user_obj)
            # print(user_obj.username)
            # print(user_obj.email)
            if user_obj:
                auth.login(request, user_obj)
                # 1.设置session值,
                # 2.request.user = user_obj.user
                #settings.py 中的中间件:from django.contrib.auth.middleware import AuthenticationMiddleware  里面process_request方法  得到auth传递的request.user = user_obj.user
                path = request.GET.get('next') or "/index/"
                return redirect(path)
    
        return render(request,"login1.html")
    
    
    def auth_logout(request):
        auth.logout(request)  # 1.清除session信息  2.把request.user 重新赋值为匿名用户。
        return redirect("/auth_login/")
    
    
    #python manager.py createsuperuser创建用户
    app01/views.py--auth模块使用
    # from django.conf import global_settings
    # from django.conf import settings
    LOGIN_URL = '/auth_login/'
    settings配置LOGIN_URL 修改模块的全局配置

    二、User对象

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

    2.1 、user对象的 is_authenticated()

    如果是真正的 User 对象,返回值恒为 True 。 用于检查用户是否已经通过了认证。
    通过认证并不意味着用户拥有任何权限,甚至也不检查该用户是否处于激活状态,这只是表明用户成功的通过了认证。 这个方法很重要, 在后台用request.user.is_authenticated()判断用户是否已经登录,如果true则可以向前台展示request.user.name

    要求:

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

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

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

    方法1:

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

    方法2:

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

    1
    2
    3
    4
    5
    from django.contrib.auth.decorators import login_required
          
    @login_required
    def my_view(request):
      ...

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

    2.2 、创建用户

    使用 create_user 辅助函数创建用户:

    1
    2
    from django.contrib.auth.models import User
    user = User.objects.create_user(username='',password='',email='')

    2.3 、check_password(passwd)

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

    2.4 、修改密码

    使用 set_password() 来修改密码

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

    2.5 、简单示例

    注册:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    def sign_up(request):
     
        state = None
        if request.method == 'POST':
     
            password = request.POST.get('password', '')
            repeat_password = request.POST.get('repeat_password', '')
            email=request.POST.get('email', '')
            username = request.POST.get('username', '')
            if User.objects.filter(username=username):
                    state = 'user_exist'
            else:
                    new_user = User.objects.create_user(username=username, password=password,email=email)
                    new_user.save()
     
                    return redirect('/book/')
        content = {
            'state': state,
            'user'None,
        }
        return render(request, 'sign_up.html', content)  

    修改密码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    @login_required
    def set_password(request):
        user = request.user
        state = None
        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:
                    state = 'empty'
                elif new_password != repeat_password:
                    state = 'repeat_error'
                else:
                    user.set_password(new_password)
                    user.save()
                    return redirect("/log_in/")
            else:
                state = 'password_error'
        content = {
            'user': user,
            'state': state,
        }
        return render(request, 'set_password.html', content)

      

    from django.shortcuts import render, HttpResponse, redirect
    from app01.MyForms import EmpForm
    from app01 import models
    from django.contrib import auth
    from django.contrib.auth.decorators import login_required  #auth自带的装饰器
    # Create your views here.
    from django.contrib.auth.models import User
    
    
    
    # @login_required
    @login_required
    def index(request):
        user = "alexjsdsb"
        pwd = "dsb945"
        # User.objects.create(username=user, password=pwd)  # 常规清空下,这样创建用户。密码不安全。明文。
        # user_obj = User.objects.create_user(username=user, password=pwd)  # 创建普通用户
        user_obj = User.objects.create_superuser(username=user, password=pwd, email="alex@163.com")  # 创建超级用户。
        print(1111, user_obj)
        return HttpResponse("这是主页。。。")
    
    # @login_required
    @login_required
    def order(request):
        return HttpResponse("这是订单。。。")
    
    
    def logout(request):
        request.session.flush()
        return redirect("/login/")
    
    
    def auth_login(request):
        if request.method == "POST":
            user = request.POST.get("user")
            pwd = request.POST.get("pwd")
            user_obj = auth.authenticate(username=user, password=pwd)  # 过滤合法用户。有则返回该对象,无,返回None
            print(user_obj, type(user_obj))
            print(user_obj)
            # print(user_obj.username)
            # print(user_obj.email)
            if user_obj:
                auth.login(request, user_obj)  # 1.设置session值,request.user = user_obj
                path = request.GET.get('next') or "/index/"
                return redirect(path)
    
        return render(request,"login1.html")
    
    
    def auth_logout(request):
        auth.logout(request)  # 1.清楚session信息  2.把request.user 重新赋值为匿名用户。
        return redirect("/auth_login/")
    app01/views.py小栗子 其它的文件跟auth模块使用一样
     
  • 相关阅读:
    文件路径选择中的三态逻辑
    .net版本号
    使用MSBuild编译vs多个解决方案
    CEF截图
    使用SharpZIpLib写的压缩解压操作类
    软件试用期设置
    list转datatable
    excel 导入
    网站登录简单验证码
    UEditor编辑器
  • 原文地址:https://www.cnblogs.com/linux985/p/10954964.html
Copyright © 2011-2022 走看看