Auth模块、Forms组件

Auth模块

auth模块是Django自带的用户认证模块:

我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统。此时我们需要实现包括用户注册、用户登录、用户认证、注销、修改密码等功能,这还真是个麻烦的事情呢。

Django作为一个完美主义者的终极框架,当然也会想到用户的这些痛点。它内置了强大的用户认证系统--auth,它默认使用 auth_user 表来存储用户数据。

 为了方便快捷的帮开发者完成登录相关的认证交互功能。

auth_user表常用操作:

from django.contrib.auth.models import User
#创建普通用户
User.objects.create_user(username='Owen', password='123')

#创建超级用户
User.objects.create_superuser(username='root',password='root',email='root@root.com')

#获取第一个用户
user = User.objects.first()

#修改密码
user.set_password('000')
user.save()  #注:修改完成后必须要进行保存,即执行save()方法

#校验密码
res = user.check_password('000')

auth组件常用功能:

# 校验用户账号及密码,校验成功返回user对象
from django.contrib.auth import authenticate
#该模块需要两个参数,用户名和密码
user=authenticate(username=usr, password=pwd)

# 注册用户到request对象中,注册成功可以用request.user访问当前登录用户(会形成session记录)
from django.contrib.auth import login
login(request, user)  # 注册authenticate成功(当前登录)的用户

# 注销当前注册的user(用户注销)
from django.contrib.auth import logout
logout(request)

# 校验用户登录状态
# 视图函数中使用
if request.user.is_authenticated(): pass
# 模板语言中使用
{% if request.user.is_authenticated %}
{% else %}
{% endif %}

# 校验登录状态的装饰器
from django.contrib.auth.decorators import login_required
@login_required(login_url='/user_login/')
def user_home(request):
    return render(request, 'user.html', locals())

 

若用户没有登录,则会跳转到django默认的 登录URL '/accounts/login/ ' 并传递当前访问url的绝对路径 (登陆成功后,会重定向到该路径)。

如果需要自定义登录的URL,则需要在settings.py文件中通过LOGIN_URL进行修改。

# 在settings.py中设置:
LOGIN_URL = '/login/'  # 这里配置成你项目登录页面的路由

扩展User表:

# app/models.py
#第一种方式:(建议使用)
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
    # 增加自定义字段
    info = models.TextField(null=True)
    
# settings.py配置
AUTH_USER_MODEL = 'app.User'

# 在视图函数中导入的模块就是:
from app.models import User


#第二种方式:(不建议使用) from django.contrib.auth.models import User Create your models here. class UserInfo(models.Model): id = models.AutoField(primary_key=True) info = models.TextField(null=True) user = models.OneToOneField(to=User, to_field='username', db_constraint=False, null=True, on_delete=models.SET_NULL)

Forms组件

表单字段的校验:

<!-- register.html核心代码 -->
<form action="" method="post" novalidate>
    <input type="text" name="usr">
    <input type="password" name="pwd">
    <input type="email" name="email">
    <input type="submit" value="注册">
</form>
# views.py核心代码
from django.shortcuts import render, HttpResponse
from django import forms
# 自定义校验表单字段的类,继承forms.Form,并用forms下具体字段完成校验
class CheckForm(forms.Form):
    # 通过error_messages自定义错误信息
    usr = forms.CharField(min_length=3, max_length=10, error_messages={'min_length':'长度至少为3'})
    pwd = forms.CharField(min_length=3, max_length=10)
    email = forms.EmailField(error_messages={'invalid':'邮箱不合法', 'required': '必填项'})

def register(request):
    if request.method == "GET":
        return render(request, 'register.html')
    if request.method == "POST":
        # 校验请求的所有数据
        check_form = CheckForm(request.POST)
        if check_form.is_valid():
            # 查看校验成功的数据,为字典类型
            print(check_form.cleaned_data)
            return HttpResponse('注册成功')
        else:
            # 查看校验失败的数据,为封装的字典类型
            print(check_form.errors)
    return HttpResponse('注册失败')

表单元素的渲染:

# view.py改动代码
class CheckForm(forms.Form):
    usr = forms.CharField(min_length=3, max_length=10, label="用户名")
    pwd = forms.CharField(min_length=3, max_length=10, label="密码")
    email = forms.EmailField(, label="邮箱")

def register(request):
    if request.method == "GET":
        check_form = CheckForm()
        return render(request, 'register.html', {'check_form': check_form})
<!-- register.html核心代码 -->
<!-- 方式一 -->
<form action="" method="post">
    {{ check_form.usr }}
    {{ check_form.pwd }}
    {{ check_form.email }}
    <input type="submit" value="注册">
</form>
<!-- 方式二 -->
<form action="" method="post">
    {% for foo in check_form %}   
         <label for="{{ foo.id_for_label }}" class="col-sm-2 control-label">{{ foo.label }}</label>       
         {{ foo }}  
     {% endfor %}
    <input type="submit" value="注册">
</form>
<!-- 方式三 -->
<form action="" method="post">
    <table>{{ check_form.as_table}}</table>
    <input type="submit" value="注册">
</form>
<!-- 方式四 -->
<form action="" method="post">
    <ul>{{ check_form.as_ul}}</ul>
    <input type="submit" value="注册">
</form>
<!-- 方式五 -->
<form action="" method="post">
    {{ check_form.as_p}}
    <input type="submit" value="注册">
</form>

错误信息的渲染:

# views.py
class CheckForm(forms.Form):
    usr = forms.CharField(
        min_length=3,
        max_length=10,
        error_messages={
            'min_length': '长度至少为3',
            'max_length': '长度最多为10',
            'required': '必填项'
        },
        label="用户名"
    )
    pwd = forms.CharField(
        min_length=3,
        max_length=10,
        error_messages={
            'min_length': '长度至少为3',
            'max_length': '长度最多为10',
            'required': '必填项'
        },
        label="密码"
    )
    email = forms.EmailField(
        error_messages={
            'invalid': '邮箱不合法',
            'required': '必填项'}
    )

def register(request):
    if request.method == "GET":
        check_form = CheckForm()
    if request.method == "POST":
        check_form = CheckForm(request.POST)
        if check_form.is_valid():
            return HttpResponse('注册成功')
    return render(request, 'register.html', locals())
<form action="" method="post" novalidate>
    {% for ele in check_form %}
    <p>
        {{ ele.label }}:{{ ele }}
        <span style="color: red">{{ ele.errors.0 }}</span>
    </p>
    {% endfor %}

    <input type="submit" value="注册">
</form>

组件的参数设置:

class Ret(Form):
    name = forms.CharField(max_length=10, min_length=2, label='用户名',
                           error_messages={'required': '该字段不能为空', 'invalid': '格式错误', 'max_length': '太长',
                                           'min_length': '太短'},
                           widget=widgets.TextInput(attrs={'class':'form-control'}))
    pwd = forms.CharField(max_length=10, min_length=2, widget=widgets.PasswordInput(attrs={'class':'form-control'}))
    email = forms.EmailField(label='邮箱', error_messages={'required': '该字段不能为空', 'invalid': '格式错误'})

局部钩子:

# 在自定义验证类CheckForm中添加局部验证钩子
class CheckForm(forms.Form):
    ...
    def clean_usr(self):
        name = self.cleaned_data.get('usr')  # type: str
        import re
        if re.match('^[0-9]', name):
            from django.core.exceptions import ValidationError
            raise ValidationError('不能以数字开头')
        return name

全局钩子:

# views.py
class CheckForm(forms.Form):
    usr = forms.CharField(
        min_length=3,
        max_length=10,
        error_messages={
            'min_length': '长度至少为3',
            'max_length': '长度最多为10',
            'required': '必填项'
        },
        label="用户名",
        widget=forms.TextInput(attrs={'placeholder': '请输入用户名'})
    )
    pwd = forms.CharField(
        min_length=3,
        max_length=10,
        error_messages={
            'min_length': '长度至少为3',
            'max_length': '长度最多为10',
            'required': '必填项'
        },
        label="密码",
        widget=forms.PasswordInput(attrs={'placeholder': '请输入密码'})
    )
    re_pwd = forms.CharField(
        min_length=3,
        max_length=10,
        error_messages={
            'min_length': '长度至少为3',
            'max_length': '长度最多为10',
            'required': '必填项'
        },
        label="确认密码",
        widget=forms.PasswordInput(attrs={'placeholder': '请确认密码'})
    )
    def clean(self):
        pwd = self.cleaned_data.get('pwd')
        re_pwd = self.cleaned_data.get('re_pwd')
        if pwd == re_pwd:
            return self.cleaned_data
        from django.core.exceptions import ValidationError
        raise ValidationError('两次密码不一致')

def register(request):
    if request.method == "GET":
        check_form = CheckForm()
    if request.method == "POST":
        check_form = CheckForm(request.POST)
        if check_form.is_valid():
            return HttpResponse('注册成功')
        else:
            # 拿到全局钩子抛出的错误信息
            all_error = check_form.errors.get('__all__', None)
    return render(request, 'register.html', locals())
<form action="" method="post" novalidate>
    {% for ele in check_form %}
        <p>
            {{ ele.label }}:{{ ele }}
            <span style="color: red">{{ ele.errors.0 }}</span>
            {% if ele.label == '确认密码' %}
                <span style="color: red">{{ all_error.0 }}</span>
            {% endif %}
        </p>
    {% endfor %}
    <input type="submit" value="注册">
</form>
原文地址:https://www.cnblogs.com/wangke0917/p/10526257.html