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

本文详细介绍了Django框架中的表单验证,包括局部和全局钩子函数的使用,以及fields参数、validators和widget的配置。同时,文章探讨了ModelForm的简单应用,以及如何在视图中处理表单数据。此外,还讲解了Cookie和Session的基本概念和在Django中的操作,包括设置、获取和使用Cookie进行登录验证的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

系列文章目录

第一章 django安装与介绍

第二章 django基础使用

第三章 路由层

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

第五章 模板层

第六章 模型层(上)

第七章 模型层(下)

第八章 ajax

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

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



一、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': '密码不能为空',
    })
<think>好的,我现在需要帮助用户详细了解Django的MVC框架结构。首先,用户已经提到参考了三个引用内容,所以我要先仔细阅读这些引用,确保正确引用信息。 第一个引用提到Django的MTV模式,将Model、Template、View对应到MVC的不同部分。我需要解释清楚MTV和MVC之间的关系,可能用户对这两个概念有混淆,需要明确区分。 第二个引用是关于Django项目的初始配置,比如INSTALLED_APPS中的默认应用。这部分可能和MVC结构关系不大,但可能需要提到Django内置的一些组件如何支持MVC架构,比如admin、auth等模块属于Model或Controller层。 第三个引用涉及到表单处理、cookiesession。这里可能需要说明在Django中,如何处理用户输入(Controller部分),以及如何视图和模板交互。例如,表单类属于View层还是Controller层?可能需要指出Django的Form和ModelForm属于View的一部分,负责数据的验证和展示。 接下来,用户的问题是“Django MVC 框架详解”,但Django实际上采用的是MTV模式,所以需要解释清楚为什么Django被称为MVC框架,同时又是MTV模式。这里需要比较传统的MVC(如Spring MVC)和Django的MTV之间的对应关系:Model对应Model,View对应Controller,Template对应View。 然后,按照系统级指令的要求,回答需要结构清晰,分点讲解。可能需要分为以下几个部分: 1. MVCMTV的对应关系 2. 各组件的作用(Model、View、Template) 3. 数据流:用户请求如何经过Django的处理流程(URLconf→View→Model→Template→响应) 4. 引用内容相关的例子,比如表单处理(引用3中的FInfo类)属于View层的责任,如何实现数据验证和展示。 5. 可能还需要提到Django的Admin站点(引用2中的INSTALLED_APPS包含admin)作为自动生成管理界面,属于Model和View的结合。 在回答过程中,需要确保正确使用LaTeX格式,比如提及类名或代码时使用行内公式的格式,例如`$FInfo$`类。不过,用户提供的引用中代码示例是Python,所以可能需要用代码块来展示,但根据用户示例中的代码块使用,可能需要用三个反引号包裹代码示例,如引用3中的表单类。但根据系统指令,用户不可见层中的示例显示代码块是被允许的,所以回答中如果有代码示例,也需要用代码块格式。 另外,用户要求生成相关问题,需要根据回答内容提出三个相关问题,例如关于MTVMVC的区别、数据流的具体步骤、表单处理在MVC中的位置等。 最后,确保引用标记正确,每个引用对应的内容在适当的位置标注,如提到MTV结构时引用[^1],提到表单处理时引用[^3],提到初始配置时引用[^2]。 现在整理思路,组织成结构化的回答: 1. 解释Django的MTV框架MVC的对应关系,引用。 2. 分点介绍Model、Template、View各自的职责,结合引用中的例子,如Model使用Django ORM,Template负责展示,View处理逻辑。 3. 数据流过程:从请求到响应的步骤,URL配置映射到View,View操作Model,传递数据到Template。 4. 引用中的实例,如表单类FInfo在View中的作用,处理用户输入(引用)。 5. 提到Django Admin作为内置应用,属于Model和View的结合(引用[^2]中的admin应用)。 6. 相关问题部分,围绕MTV结构、数据流、组件交互等方面提问。 需要确保LaTeX格式正确,比如在提到类名或代码变量时使用$...$,但实际检查用户示例中的代码块,如“def quick_sort...”是使用代码块,而变量如$x^2$使用行内公式。但根据系统级指令,行内数学表达式需要用$...$,而独立公式用$$...$$。在Django框架的解析中可能数学公式较少,更多的是代码和术语,因此需要注意是否需要使用LaTeX。例如,如果提到变量名或类名,可能不需要数学公式,但若有表达式可能需要,比如在说明URL匹配模式时,若使用正则表达式,可以用$...$包裹,例如`^articles/(\d+)/$`,但用户示例中的代码块是Python代码,所以可能直接使用代码块更合适。 因此,在回答中,代码部分使用代码块,术语如类名、函数名用反引号,而数学表达式使用$...$。例如,如果有涉及到的数学内容,比如分页的页码计算,可能会需要,但当前问题可能不涉及。因此,可能不需要使用数学公式,但需要遵循指令中的要求,确保所有数学相关内容正确格式化。 最后,生成的相关问题需要Django的MVC/MTV结构相关,例如优化数据流、模板继承机制、表单处理最佳实践等。</think>### Django MVC框架详解 虽然Django官方文档中更倾向于使用**MTV模式**(Model-Template-View)的表述,但其本质传统的**MVC模式**(Model-View-Controller)高度对应。以下是两者的映射关系及Django组件的作用: #### 1. MVCMTV的对应关系 | MVC模式 | MTV模式 | 职责描述 | |---------------|---------------|--------------------------------------------------------------------------| | **Model** | **Model** | 定义数据结构,操作数据库(通过ORM实现) | | **View** | **View** | 处理业务逻辑,充当控制器角色(接收请求、操作模型、返回响应) | | **Controller**| **Template** | 负责数据展示,渲染用户界面(HTML模板) | #### 2. 核心组件详解 - **Model(模型)** 通过Django ORM(对象关系映射)定义数据表结构关系。例如: ```python from django.db import models class Article(models.Model): title = models.CharField(max_length=200) content = models.TextField() ``` 模型直接数据库交互,支持数据验证和业务规则实现。 - **View(视图)** 接收HTTP请求,处理逻辑,返回响应。例如表单验证: ```python from django.shortcuts import render from .forms import FInfo # 引用中的表单类 def article_view(request): if request.method == 'POST': form = FInfo(request.POST) if form.is_valid(): # 处理有效数据 return HttpResponse("提交成功") return render(request, 'form_template.html', {'form': form}) ``` View层负责协调Model和Template,类似于MVC中的Controller[^1]。 - **Template(模板)** 使用Django模板语言(DTL)动态生成HTML。例如显示文章列表: ```html {% for article in articles %} <h2>{{ article.title }}</h2> <p>{{ article.content }}</p> {% endfor %} ``` #### 3. 数据流示例 1. **用户请求**:浏览器访问`/articles/1/` 2. **URL路由**:`urls.py`映射到对应的视图函数 ```python urlpatterns = [ path('articles/<int:id>/', article_view, name='article_detail'), ] ``` 3. **视图处理**:`article_view`函数从数据库获取数据 4. **模板渲染**:数据填充到HTML模板,生成最终页面 #### 4. 内置功能扩展 - **Admin站点**:通过`django.contrib.admin`(引用)自动生成管理界面,直接操作Model数据。 - **表单处理**:如`FInfo`类(引用)通过`forms.Form`或`forms.ModelForm`实现数据验证展示的统一。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值