django框架——forms组件(下)、ModelForm简单使用、cookie与session简单使用

系列文章目录

第一章 django安装与介绍

第二章 django基础使用

第三章 路由层

第四章 虚拟环境、django版本区别、视图层

第五章 模板层

第六章 模型层(上)

第七章 模型层(下)

第八章 ajax

第九章 sweetalert前端插件、序列化组件、批量数据操作、分页器、Forms组件(上)

第十章 forms组件(下)、ModelForm简单使用、cookie与session简单使用


文章目录

  • 系列文章目录
  • 一、forms组件钩子函数
    • 1.局部钩子
    • 2.全局钩子
  • 二、forms组件字段参数
  • 三、forms组件字段类型
  • 四、forms组件源码分析
  • 五、ModelForm简单使用
  • 六、cookie与session简单使用
    • cookie简介
    • session
    • django操作cookie
      • 基本使用


一、forms组件钩子函数

钩子函数的含义其实就是在程序的执行过程中穿插额外的逻辑,钩子函数是数据经过了字段第一层参数校验之后才会执行

使用钩子函数之前需要建立form组件类

from django import forms
from app01 import models
from django.core.exceptions import ValidationError

class MyForm(forms.Form):
    username = forms.CharField(max_length=20, min_length=6,label='用户名', error_messages={
        'min_length': '用户名最短为6位',
        'max_lenght': '用户名最长为16位',
        'required': '用户名不能为空',
    })
    password = forms.CharField(max_length=16, min_length=6,label='密码',error_messages={
        'min_length': '用户名最短为6位',
        'max_lenght': '用户名最长为16位',
        'required': '密码不能为空',
    })
    email = forms.EmailField(required=True,label='邮箱', error_messages={
        'invalid':'邮箱格式错误',
    })

1.局部钩子

局部钩子只是针对form组件中的一个字段

eg:
使用局部钩子检测用户名是否存在

    def clean_username(self):
        username = self.cleaned_data.get('username')
        is_has = models.User.objects.filter(username=username)
        if is_has:
            # self.add_error("username", "用户名已存在")  # form组件提供的错误信息方法
            raise ValidationError('用户名已存在') # 通过分析form组件代码发现可以使用python的异常来提供错误信息
        return username

2.全局钩子

全局钩子针对form组件中的全部字段

eg:
使用全局钩子检测密码开头是否为大写字母

    def clean(self):
        # 1.获取字段数据
        password = self.cleaned_data.get('password')
        if not re.findall('^[A-Z]', password):
            self.add_error('password', "密码开头必须为大写字母")
        # 最后将整个数据返回
        return self.cleaned_data

二、forms组件字段参数

参数名 参数作用
min_length 最小长度
max_length 最大长度
label 字段名称
error_messages 错误提示
min_value 最小值
max_value 最大值
initial 默认值
validators 正则校验器
widget 控制渲染出来的标签各项属性
choices 选择类型的标签内部对应关系

eg:

validators使用示例

from django.core.validators import RegexValidator
  phone = forms.CharField(
        validators=[
                    RegexValidator(r'^[0-9]+$', '请输入数字'),
                    RegexValidator(r'^184[0-9]+$', '数字必须以184开头')],
                    # RegexValidator可以使用多个他们之间的关系为且
    )

widget使用示例

forms.widgets.控制type的类型(attrs=控制各项属性:class id 等标签属性…)

password = forms.CharField(                          widget=forms.widgets.PasswordInput(attrs={'class':'form-control'})
)
  

三、forms组件字段类型

Field
    required=True,               是否允许为空
    widget=None,                 HTML插件
    label=None,                  用于生成Label标签或显示内容
    initial=None,                初始值
    help_text='',                帮助信息(在标签旁边显示)
    error_messages=None,         错误信息 {'required': '不能为空', 'invalid': '格式错误'}
    validators=[],               自定义验证规则
    localize=False,              是否支持本地化
    disabled=False,              是否可以编辑
    label_suffix=None            Label内容后缀
 
 
CharField(Field)
    max_length=None,             最大长度
    min_length=None,             最小长度
    strip=True                   是否移除用户输入空白
 
IntegerField(Field)
    max_value=None,              最大值
    min_value=None,              最小值
 
FloatField(IntegerField)
    ...
 
DecimalField(IntegerField)
    max_value=None,              最大值
    min_value=None,              最小值
    max_digits=None,             总长度
    decimal_places=None,         小数位长度
 
BaseTemporalField(Field)
    input_formats=None          时间格式化   
 
DateField(BaseTemporalField)    格式:2015-09-01
TimeField(BaseTemporalField)    格式:11:12
DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
 
DurationField(Field)            时间间隔:%d %H:%M:%S.%f
    ...
 
RegexField(CharField)
    regex,                      自定制正则表达式
    max_length=None,            最大长度
    min_length=None,            最小长度
    error_message=None,         忽略,错误信息使用 error_messages={'invalid': '...'}
 
EmailField(CharField)      
    ...
 
FileField(Field)
    allow_empty_file=False     是否允许空文件
 
ImageField(FileField)      
    ...
    注:需要PIL模块,pip3 install Pillow
    以上两个字典使用时,需要注意两点:
        - form表单中 enctype="multipart/form-data"
        - view函数中 obj = MyForm(request.POST, request.FILES)

四、forms组件源码分析

# 1.
class Form(six.with_metaclass(DeclarativeFieldsMetaclass, BaseForm)):

# 2.
class BaseForm(object):
	def __init__(self, data=None, files=None, # 此处指列举了一部分 这俩个参数很重要

# 3.一些form组件的常用属性方法都在BaseForm中
@property
    def errors(self): # 错误信息的处理方法

def is_valid(self): # form组件获取的数据验证是否为true的方法

def as_table(self): # form组件渲染标签

def as_ul(self):# form组件渲染标签

def as_p(self):# form组件渲染标签


五、ModelForm简单使用

forms组件主要配合models里面的默写类一起使用 但是默写类里面的字段需要在forms类中相当于重写一遍,代码冗余所以django将model和form结合起来制作了一个更方便的类,目前先简单使用

class MyUser(forms.ModelForm):
    class Meta: # 此处类名必须是Meta
        model = models.User  # 指定关联的表
        fields = '__all__'  # 所有的字段全部生成对应的forms字段 
        labels = { # label标签名字
            'username': '用户名',
			'password': '密码',
            'email': '邮箱'
        }
        widgets = { # 标签样式
            "name": forms.widgets.TextInput(attrs={"class": "form-control"}),
        }

eg:
代码示例

1.创建modelform继承类

class MyModelForm(forms.ModelForm):
    class Meta:
        model = models.User
        fields = '__all__'
        labels = {
            'username': '用户名',
            'password': '密码',
            'email': '邮箱'
        }
        widgets = {
            "username": forms.widgets.TextInput(attrs={"class": "form-control"}),
            "password": forms.widgets.PasswordInput(attrs={"class": "form-control"}),
            "email": forms.widgets.EmailInput(attrs={"class": "form-control"}),
        }

2.视图层

def register(request):
    datas = request.POST
    form = MyModelForm()
    # user = models.User.objects.filter(username=form.cleaned_data.get('username')).first()
    if request.method == 'POST':
        # 此处可以添加一个关键字参数来选择是更新还是新增
        form = MyModelForm(data=datas) # 没有添加instance所以是新增
        # form = MyModelForm(datas, instance=user) # 添加instance指定对那个对象镜像修改所以是更新
        if form.is_valid():
            form.save()  # 执行数据的更新或者新增
            # models.User.objects.create(**form.cleaned_data)# 使用form组件时的新增数据
            # models.User.objects.filter(username=form.cleaned_data.get('username')).update(**form.cleaned_data)# 使用form组件时的更新数据
    return render(request, 'register.html', locals())

3.模板层

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册title>
    <link rel="stylesheet" href="/static/bootstrap-3.4.1-dist/css/bootstrap.css">
head>
<body>
    <div class="container">
        <form action="" method="post">
            {% for foo in form %}
                <div class="row">
                    <label>{{ foo.label }}label>
                    {{ foo }}<span style="color: red">{{ foo.errors.0 }}span>
                div>
            {% endfor %}
            <input type="submit" value="注册" class="btn-success btn btn-default">
        form>
    div>
body>
html>

六、cookie与session简单使用

cookie简介

Cookie翻译成中文的意思是‘小甜饼’,是由W3C组织提出,最早由Netscape社区发展的一种机制。目前Cookie已经成为标准,所有的主流浏览器如IE、Netscape、Firefox、Opera等都支持Cookie。

服务器单从网络连接上无从知道客户身份。怎么办呢?就给客户端们颁发一个通行证吧,每人一个,无论谁访问都必须携带自己通行证。这样服务器就能从通行证上确认客户身份了。这就是Cookie的工作原理。

Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式。Cookie存储的数据量有限,且都是保存在客户端浏览器中。不同的浏览器有不同的存储大小,但一般不超过4KB。因此使用Cookie实际上只能存储一小段的文本信息(key-value格式)。

session

在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下)。因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session中,当用户使用浏览器访问其它程序时,其它程序可以从用户的session中取出该用户的数据,为用户服务。

django操作cookie

基本使用

return HttpResonse()
return render()
return redirect()

不直接返回对象 而是先用变量名指代 然后操作对象方法
res = HttpResonse()
res.set_cookie()
return res
res = render()
return res
res = redirect()
return res

res.set_cookie() # 设置
res.COOKIE.get() # 获取

有很多视图函数需要添加登录认证 有时候又需要取消登录认证这个时候需要使用装饰器

示例:
未登陆时无法进入首页或主页,未登录用户在访问主页或首页时会自动跳转到登录页面,但登陆完毕后会跳转回之前想访问的页面

登录装饰器:

from django.shortcuts import redirect

def is_login(func):
    def inner(request, *args, **kwargs):
        url = request.path
        if not request.COOKIES:
            return redirect(f'/login/?last={url}')
        res = func(request, *args, **kwargs)
        return res
    return inner

登录视图函数:

def login(request):
    form = MyForm1()
    if request.method == 'POST':
        datas = request.POST
        form = MyForm1(datas)
        if form.is_valid():
            username = form.cleaned_data.get('username')
            uobj = models.User.objects.filter(username=username)
            if uobj:
                password = form.cleaned_data.get('password')
                if password == uobj.first().password:
                    if not request.GET:
                        response = redirect('/home/')
                        response.set_cookie('username', username)
                        return response
                    url = request.GET["last"]
                    response = redirect(url)
                    response.set_cookie('username', username)
                    return response
    return render(request, 'login.html', locals())

主页和首页的视图函数

@is_login
def home(request):
    username = request.COOKIES.get("username")
    return render(request, 'home.html', locals())

@is_login
def index(request):
    username = request.COOKIES.get('username')
    return render(request, 'index.html', locals())

form组件

from django import forms
from app01 import models
from django.core.exceptions import ValidationError
import re

class MyForm(forms.Form):
    username = forms.CharField(max_length=20, min_length=6,label='用户名', error_messages={
        'min_length': '用户名最短为6位',
        'max_lenght': '用户名最长为16位',
        'required': '用户名不能为空',
    })
    password = forms.CharField(max_length=16, min_length=6,label='密码',error_messages={
        'min_length': '用户名最短为6位',
        'max_lenght': '用户名最长为16位',
        'required': '密码不能为空',
    })
    email = forms.EmailField(required=True,label='邮箱', error_messages={
        'invalid':'邮箱格式错误',
    })

    def clean(self):
        # 1.获取字段数据
        password = self.cleaned_data.get('password')
        if not re.findall('^[A-Z]', password):
            self.add_error('password', "密码开头必须为大写字母")
        # 最后将整个数据返回

        username = self.cleaned_data.get('username')
        is_has = models.User.objects.filter(username=username)
        if is_has:
            # self.add_error("username", "用户名已存在")  # form组件提供的错误信息方法
            raise ValidationError('用户名已存在')  # 通过分析form组件代码发现可以使用python的异常来提供错误信息
        return self.cleaned_data

class MyForm1(forms.Form):
    username = forms.CharField(max_length=20, min_length=6, label='用户名', error_messages={
        'min_length': '用户名最短为6位',
        'max_lenght': '用户名最长为16位',
        'required': '用户名不能为空',
    })
    password = forms.CharField(max_length=16, min_length=6, label='密码', error_messages={
        'min_length': '用户名最短为6位',
        'max_lenght': '用户名最长为16位',
        'required': '密码不能为空',
    })

你可能感兴趣的:(django框架,web框架,django,python,前端)