Auth组件,Forms组件

一、Auth组件默认auth_user表常用操作

#1.配置settings,使django与数据库连接
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'dg74_1',
        'USER': 'root',
        'PASSWORD': "940828",
        'HOST': '127.0.0.1'
    }
}

#2.
import pymysql
pymysql.install_as_MySQLdb()

#3.直接进行数据库迁移,这样django就会在数据库中建立出一个auth_user表



#操作auth_user 数据库不区分大小写
from django.contrib.auth.models import User
# 1、创建普通用户
User.objects.create_user(username='Henry',password='123')

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

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

# 4、修改密码
user.set_password('000')
user.save()

# 5、校验密码
res = user.check_password('000')
print(res) 校验成功:True 校验失败:False

二、Auth组件常用功能

# 1、校验用户账号及密码,校验成功返回user对象
from django.contrib.auth import authenticate
user = authenticate(username=usr, password=pwd)

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

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

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

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

后台

from django.shortcuts import render,redirect
from django.contrib.auth import login,logout,authenticate
from django.contrib.auth.decorators import login_required

def index(request):
    return render(request,'index.html')

def user_login(request):
    if request.method == 'GET':
        return render(request,'login.html')
    if request.method == 'POST':
        #在请求url中通过next取出回跳的页面路径,因为使用?拼接所以用get取值,没有值返回主页
        back_url = request.GET.get('next','/')
        usr = request.POST.get('usr',None)
        pwd = request.POST.get('pwd',None)

        #用前台传入的账户密码进行登录校验
        user = authenticate(username=usr,password=pwd)

        if user:
            #记录登录状态
            login(request,user)
        return redirect(back_url)

def user_logout(request):
    logout(request)
    return redirect('/')

#装饰器的页面返回key是next:/user_login/?next=/user_order/
@login_required(login_url='/user_login/') #没有登录返回登录界面,登录成功又跳转回该页面
def user_order(request):
    return render(request,'order.html',locals())

@login_required(login_url='/user_login/')
def user_home(request):
    return render(request,'user.html',locals())

前台

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<h1>主页</h1>

<p>
    {% if request.user.is_authenticated %} 
        <a href="/user_home/">{{ request.user.username }}</a>
        |
        <a href="/user_logout/">注销</a>
    {% else %}
        <a href="/user_login/">登录</a>
    {% endif %}
</p>
<hr>
<a href="/user_order/">订单详情</a>

</body>
</html>


//{% if request.user.is_authenticated %}  检验用户登录状态
//request.user.username 固定的取法,取得登录的用户名

三、自定义auth模块的user表,将auth_user表替换为app_user表

# app/models.py
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
    # 增加自定义字段
	info = models.TextField(null=True)
    
# settings.py配置,auth模块默认采用的是app应用下的自定义user表
AUTH_USER_MODEL = 'app.User'

#数据库迁移后auth_user表不再创建由app_user表替换

四、Form完成表单校验 (自定义错误信息)

'''
1. 校验的字段属性名要与校验的form表单中元素的name值进行匹配
2. 校验字段的参数required
默认为True,代表数据必须传入该校验值
如果设置为False,校验数据中可以不包含该校验值(可以为空),但如果输入了该字段就会对其进行校验
3. error_messages自定义校验失败的错误信息
'''

'''
from django import forms
class CheckForm(forms.Form):
    usr = forms.CharField(min_length=3, max_length=10)
    pwd = forms.CharField(
        min_length=3,
        max_length=10,
        error_messages={
            "min_length": "最少3",  # 某个校验规则对应的中文提示的错误信息
            "max_length": "最多10",
            'required': "必填项"  # 除了自定义校验规则,还可以明确默认校验规则的中文提示错误信息
        }
    )

def register(request):
    check_form = CheckForm(request.POST)
    if check_form.is_valid():
            print("校验成功")
            print(check_form.cleaned_data)
        else:
            print("校验失败")
            print(check_form.cleaned_data)  # 如果部分成功,仍然可以获得部分成功的数据
            print(check_form.errors)  # 部分失败的信息
'''

五、局部钩子:在系统提供的校验结束后,在对具体的字段进行自定义二次校验

class CheckForm(forms.Form):
    usr = forms.CharField(...)
    # ...
    # 局部钩子
    def clean_usr(self):
        cleaned_usr = self.cleaned_data.get('usr', None)
        # 自定义校验规则
        import re
        if re.match('^[0-9]', cleaned_usr):  # 通过正则匹配不能以数字开头
            from django.core.exceptions import ValidationError
            raise ValidationError('不能以数字开头')  # 抛ValidationError信息就会被添加到self.errors中
        return cleaned_usr

六、全局钩子:在系统提供的校验结束后,在对所有的字段进行自定义二次校验

class CheckForm(forms.Form):
    # ...
    # 全局钩子
    def clean(self):
        cleaned_pwd = self.cleaned_data.get('pwd', None)
        cleaned_re_pwd = self.cleaned_data.get('re_pwd', None)
        if cleaned_pwd != cleaned_re_pwd:
            from django.core.exceptions import ValidationError
            raise ValidationError('两次密码不一致')  # 抛ValidationError信息就会被添加到self.errors中
        return self.cleaned_data

后台

from django.shortcuts import render,redirect
from django import forms

class CheckForm(forms.Form):
    usr = forms.CharField(min_length=3,max_length=10,
                          error_messages={
                              'required':'必须填',
                              'min_length':'最少3',
                              'max_length':'最多10'
                          })
    pwd = forms.CharField(min_length=3,max_length=10,
                          error_messages={
                              'required':'必须填',
                              'min_length':'最少3',
                              'max_length':'最多10'
                          })
    re_pwd = forms.CharField(min_length=3,max_length=10,
                          error_messages={
                              'required':'必须填',
                              'min_length':'最少3',
                              'max_length':'最多10'
                          })
    email = forms.EmailField(
        error_messages={
            'invalid':'email格式不正确',
            'required':'必填项'
        }
    )
    # 局部钩子:对usr进行局部钩子的校验,该方法会在usr属性校验通过后,系统调用该方法继续校验,是一个回调函数
    def clean_usr(self):
        cleaned_usr = self.cleaned_data.get('usr', None)  # type: str

        # 通过正则匹配不能以数字开头
        import re
        if re.match('^[0-9]', cleaned_usr):
            from django.core.exceptions import ValidationError
            raise ValidationError('不能以数字开头')
        return cleaned_usr #返回局部钩子校验的数据

    # 全局钩子:代表校验类中的所有属性校验通过后,系统调用该方法继续校验
    def clean(self):
        cleaned_pwd = self.cleaned_data.get('pwd', None)
        cleaned_re_pwd = self.cleaned_data.get('re_pwd', None)
        if cleaned_pwd != cleaned_re_pwd:
            from django.core.exceptions import ValidationError
            raise ValidationError('两次密码不一致')  #抛出异常,必须接受,否则报错
        return self.cleaned_data  #全部返回

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('校验成功')
            print(check_form.cleaned_data)
        else:
            print('校验失败')
            print(check_form.cleaned_data)
            print(check_form.errors)
        return redirect('/')

前台

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>注册</title>
</head>
<body>
<form action="" method="post" novalidate>
    <p>
        <label for="usr">账号:</label>
        <input type="text" name="usr" id="usr">
    </p>
    <p>
        <label for="pwd">密码:</label>
        <input type="password" name="pwd" id="pwd">
    </p>
    <p>
        <label for="re_pwd">确认:</label>
        <input type="password" name="re_pwd" id="re_pwd">
    </p>
    <p>
        <label for="email">邮箱:</label>
        <input type="email" name="email" id="email">
    </p>
    <input type="submit" value="注册">
</form>
</body>
</html>

七、模板渲染

class CheckForm(forms.Form):
    # 校验需求:账号不能以数字开头
    usr = forms.CharField(min_length=3, max_length=10, label="账号:",
                          error_messages={
                              'required': "必填项",
                              'min_length': "最少3",
                              'max_length': "最多10"
                          })
    pwd = forms.CharField(min_length=3, max_length=10, label="密码:",
                          error_messages={
                              'required': "必填项",
                              'min_length': "最少3",
                              'max_length': "最多10"
                          },
                          widget=forms.PasswordInput(attrs={
                              'class': 'pwd',
                              'placeholder': '请输入密码'
                          })
                          )
    re_pwd = forms.CharField(min_length=3, max_length=10, label="确认:",
                             error_messages={
                                 'required': "必填项",
                                 'min_length': "最少3",
                                 'max_length': "最多10"
                             },
                             widget=forms.PasswordInput)
    email = forms.EmailField(label="邮箱:",
                             error_messages={
                                 'invalid': "格式不正确",
                                 'required': "必填项"
                             }
                             )

    # 局部钩子:对usr进行局部钩子的校验,该方法会在usr属性校验通过后,系统调用该方法继续校验
    def clean_usr(self):
        cleaned_usr = self.cleaned_data.get('usr', None)  # type: str
        # 通过正则匹配不能以数字开头
        import re
        if re.match('^[0-9]', cleaned_usr):
            from django.core.exceptions import ValidationError
            raise ValidationError('不能以数字开头')
        return cleaned_usr

    # 全局钩子:代表校验类中的所有属性校验通过后,系统调用该方法继续校验
    def clean(self):
        cleaned_pwd = self.cleaned_data.get('pwd', None)
        cleaned_re_pwd = self.cleaned_data.get('re_pwd', None)
        if cleaned_pwd != cleaned_re_pwd:
            from django.core.exceptions import ValidationError
            raise ValidationError('两次密码不一致')
        return self.cleaned_data


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:
            print(check_form.errors.as_data)
            all_error = check_form.errors.get('__all__')
    return render(request, 'register.html', locals())

渲染方法1

<form action="" method="post" novalidate>
    <p>
        <label for="id_usr">账号:</label>
        {{ check_form.usr }}
    </p>
    <p>
        <label for="id_pwd">密码:</label>
        {{ check_form.pwd }}
    </p>
    <p>
        <label for="id_re_pwd">确认:</label>
        {{ check_form.re_pwd }}
    </p>
    <p>
        <label for="id_email">邮箱:</label>
        {{ check_form.email }}
    </p>
    <input type="submit" value="注册">
</form>

//命名规范 id_ 这样点击输入框前的名字也可以选定输入框

渲染方法2

<form action="" method="post" novalidate>
    {% for ele in check_form %}
        <p>
            <label for="">{{ ele.label }}</label>
            {{ ele }}
            <span style="color: red;">{{ ele.errors.0 }}</span>
            {% if ele == check_form.re_pwd %}
                <span style="color: red;">{{ all_error.0 }}</span>
            {% endif %}
        </p>
    {% endfor %}
    <input type="submit" value="注册">
</form>

渲染方式3

<form action="" method="post" novalidate>
    {{ check_form.as_p }}
    <input type="submit" value="注册">
</form>
<hr>

渲染方式了解

<table>
    {{ check_form.as_table }}
</table>

<ul>
    {{ check_form.as_ul }}
</ul>
原文地址:https://www.cnblogs.com/lizeqian1994/p/10532683.html