Python学习---Form拾遗180322
Form操作之错误信息操作
1. 用户发送请求过来
2. for 循环对字段进行正则表达式的验证 fields.clean(value)
3. 自定义clean_字段() 进行名字段值正确性的校验
4. 自定义clean()的内容校验,会进行异常信息的捕捉
5. post_clean()方法的校验,不允许抛出异常,self.add_error(进行校验)
注意 self.add_error(None, ValidatorError(‘’)) 这里虽然写的是None,但实际上会转换为__all__
Django内部会进行转换的:self.add_error(‘__all__’, ValidatorError(‘’))
settings.py
INSTALLED_APPS = [
...
'app01', # 注册app
]
STATICFILES_DIRS = (os.path.join(BASE_DIR, "statics"),) # 现添加的配置,这里是元组,注意逗号
TEMPLATES = [
...
'DIRS': [os.path.join(BASE_DIR, 'templates')],
]
urls.py
from django.contrib import admin
from django.urls import path
from django.conf.urls import url, include
from app01 import views
urlpatterns = [
url('fm/', views.fm),
]
views.py
from django.shortcuts import render, redirect, HttpResponse
from app01 import models,fields
class Fm(forms.Form):
username = fields.CharField(max_length=32, label='用户名')
email = fields.EmailField(label='邮箱') # 这里是对username字段的内容进行验证的
def _clean_username(self):
data = self.cleaned_data['username']
if (data == 'root'):
return data # 验证通过,返回一个结果给forms.py中full_clean()方法的调用处
else:
from django.core.exceptions import ValidationError
# 这里的异常也是forms.py中full_clean()的异常捕获
raise ValidationError("请使用root用户登录...") # 这里实际上是调用 _clean_form(self)里的clean()进行错误拓展
def clean(self):
data = self.cleaned_data['username']
email = self.cleaned_data['email']
if (data == 'root' and email == 'root@live.com'):
pass # 因为父级别的_post_clean也是什么都不操作
else:
from django.core.exceptions import ValidationError
# 这里的异常是forms._clean_form()的异常捕获
raise ValidationError("用户名或email错误...")
return self.cleaned_data # _post_clean和_clean_form里面的clean()效果同,所以这里隐去
# 这里是个_post_clean里面的Hook,里面的方法体为空
# def _post_clean(self):
# data = self.cleaned_data['username']
# email = self.cleaned_data['email']
# if (data == 'root' and email == 'root@live.com'):
# pass # 因为父级别的_post_clean也是什么都不操作
# else:
# from django.core.exceptions import ValidationError
# # 这里的异常是forms._clean_form()的异常捕获
# raise ValidationError("用户名或email错误...") def fm(request):
if request.method == "GET":
obj = Fm()
return render(request, 'fm.html', {"obj": obj})
else:
obj = Fm(request.POST)
obj.is_valid()
# data = obj.clean() 因为Fm()里面覆写了该方法,所以直接调用cleaned_data获取值即可
data = obj.cleaned_data
error = obj.errors
print('错误信息',error)
print('正确信息:',data)
return render(request, 'fm.html', {"obj": obj})
templates/fm.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
{# 模版语言一: 逐个输出内容#}
<h5>模版语言,逐个输出</h5>
{{ obj.username }}
{{ obj.email }}
<hr>
{# 模版语言二: 一次性输出全部内容,如果是as_p,则是在P标签内,as_ul是ul标签 #}
<h5>模版语言,一次性配合lable标签输出全部字段</h5>
{{ obj.as_p }}
{{ obj.as_ul }}
<table>{{ obj.as_table }}</table>
<hr>
<form action="/fm/" method="post">
{{ obj.as_p }}
<input type="submit" value="提交"/>
</form>
</body>
</html>
页面显示;

初始化数据库
python manage.py makemigrations
python manage.py migrate
Form操作之is_valid()源码解析
进入full_clean()方法

full_clean()方法:

_clean_fields()


add_error(name,e)


_clean_form():

_post_form()

Form操作之前台下拉框实时显示数据库内容
问题现象:无法获取数据库内最新的数据


解决一: 调用父类的构造方法,每次调用函数之前重新获取数据
class Fm(forms.Form):
username = fields.CharField(max_length=32, label='用户名')
email = fields.EmailField(label='邮箱')
user_type=fields.ChoiceField(choices=models.UT.objects.values_list('id', 'caption')) def __init__(self, *args, **kwargs):
super(Fm, self).__init__(*args, **kwargs)
self.fields['user_type'].widget.choices = models.UT.objects.all().values_list('id', 'caption')


最终显示内容:

附完整源码:
settings.py
INSTALLED_APPS = [
...
'app01', # 注册app
]
STATICFILES_DIRS = (os.path.join(BASE_DIR, "statics"),) # 现添加的配置,这里是元组,注意逗号
TEMPLATES = [
...
'DIRS': [os.path.join(BASE_DIR, 'templates')],
]
urls.py
from django.contrib import admin
from django.urls import path
from django.conf.urls import url, include
from app01 import views
urlpatterns = [
url('fm/', views.fm),
]
views.py
from django.shortcuts import render, redirect, HttpResponse
from app01 import models
class Fm(forms.Form):
username = fields.CharField(max_length=32, label='用户名')
email = fields.EmailField(label='邮箱')
user_type=fields.ChoiceField(choices=models.UT.objects.values_list('id', 'caption'))
# 方案一:
def __init__(self, *args, **kwargs):
super(Fm, self).__init__(*args, **kwargs)
self.fields['user_type'].widget.choices = models.UT.objects.all().values_list('id', 'caption')
# 方案二:
from django.forms import models as filed_models
# 这里的all()返回的是一个对象,前台页面显示的始终是object,但是看源码又有value值
# 同时这里的limit_choices_to并无明显效果显示,在ModelForm里面效果显著
user_type2 = filed_models.ModelChoiceField(queryset=models.UT.objects.all(),
to_field_name='caption',
limit_choices_to={'id':'(1,3)'},)
# 多选框
user_type3 = filed_models.ModelMultipleChoiceField(queryset=models.UT.objects.all(),
to_field_name='caption',
limit_choices_to={'id': '(1,3)'}, ) def fm(request):
if request.method == "GET":
obj = Fm()
return render(request, 'fm.html', {"obj": obj})
models.py
from django.db import models
class U(models.Model):
id = models.AutoField(primary_key=True) # AutoField必须是主键,才能自定义该列
name = models.CharField(max_length=32)
email = models.CharField(max_length=32)
userType = models.ForeignKey("UT", on_delete=True) # 1对多[无法用自定义,有约束关系] class UT(models.Model):
caption = models.CharField(max_length=32)
def __str__(self):
return self.caption
templates/fm.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
{# 模版语言一: 逐个输出内容#}
<h5>模版语言,逐个输出</h5>
{{ obj.username }}
{{ obj.email }}
<hr>
{# 模版语言二: 一次性输出全部内容,如果是as_p,则是在P标签内,as_ul是ul标签 #}
<h5>模版语言,一次性配合lable标签输出全部字段</h5>
{{ obj.as_p }}
{{ obj.as_ul }}
<table>{{ obj.as_table }}</table>
<hr>
<form action="/fm/" method="post">
{{ obj.as_p }}
<input type="submit" value="提交"/>
</form>
</body>
</html>
页面显示;

初始化数据库
python manage.py makemigrations
python manage.py migrate
Form操作更多参考 :http://www.cnblogs.com/wupeiqi/articles/6144178.html
Python学习---Form拾遗180322的更多相关文章
- Python学习---Model拾遗[1]180318
Model: 强大的数据库操作,弱小的数据验证 Form: 强大的数据验证 ModelForm: 强大的数据验证 + 弱小的数据库操作 Model拾遗 Model基本操作 1. 创建数据库表2. 修 ...
- Python学习---Django拾遗180328
Django之生命周期 前台发送URL请求到Django的中间件进行内容校验,完成校验后到达路由映射文件url.py,然后调用视图函数views.py里面的函数进行内容处理[ 1.操作数据库进行数据读 ...
- Python学习---ModelForm拾遗180325
ModelForm适用于前台验证和后台直接操作数据库的前后台未做分离,可以一次执行验证和保存数据的场景. 注意: 1. ModelForm里面没有删除方法,需要手动删除内容 2. ModelFor ...
- Python学习---Model拾遗[2]180318
Model的字段及字段参数: Model字段: 数字 字符串(带正则的字段) 时间 文件 特殊字段:(一对一,一对多,多对多) Models.py ...
- Python 学习 第十篇 CMDB用户权限管理
Python 学习 第十篇 CMDB用户权限管理 2016-10-10 16:29:17 标签: python 版权声明:原创作品,谢绝转载!否则将追究法律责任. 不管是什么系统,用户权限都是至关重要 ...
- Python:Python学习总结
Python:Python学习总结 背景 PHP的$和->让人输入的手疼(PHP确实非常简洁和强大,适合WEB编程),Ruby的#.@.@@也好不到哪里(OO人员最该学习的一门语言). Pyth ...
- python学习博客地址集合。。。
python学习博客地址集合... 老师讲课博客目录 http://www.bootcdn.cn/bootstrap/ bootstrap cdn在线地址 http://www.cnblogs. ...
- python学习笔记目录
人生苦短,我学python学习笔记目录: week1 python入门week2 python基础week3 python进阶week4 python模块week5 python高阶week6 数据结 ...
- 【old】Python学习笔记
上学期看视频记得,也没学到多少,目前打算一边通过<Python学习手册 第四版>提高核心语法(太厚了 噗),一边学习Python Web开发 然后这里的多任务编程和网络编程是暑假学的 5. ...
随机推荐
- C语言中的条件编译
通常情况,我们想让程序选择性地执行,多会使用分支语句,比如if-else 或者switch-case 等.但有些时候,可能在程序的运行过程中,某个分支根本不会执行. 比如我们要写一个跨平台项目,要求项 ...
- Linux网络子系统
再Linux的世界里,万物皆文件,通过虚拟文件系统VFS,程序可以用标准的Linux系统调用对不同的文件系统,甚至不同介质上的文件系统进行读写操作.下面我们揭示Linux网络子系统的秘密 sockfs ...
- BI实战派:医疗BI项目落地方案
任何BI项目面临的两大难题是项目价值和基础数据,BI项目应该给企业带来管理优化.业绩增长.医院面临的两大难题,一:绩效管理(奖金分配):二:医患关系:在医院开始自负盈亏时日常基本运营管理显得非常重要. ...
- Class.forName(),Class.forName().newInstance() ,New ,类名.class,,class.forName(),,getClass()
在Java开发特别是数据库开发中,经常会用到Class.forName( )这个方法.通过查询Java Documentation我们会发现使用Class.forName( )静态方法的目的是为 ...
- golang基础--map字典
map 类似python语言中的dict(字典类型),以key-value形式存储数据 Key必须是支持==或!=比较运算的类型,不可以是函数,map或slice map查找比线性搜素快很多,但比使用 ...
- 编写高质量 JavaScript -- 知识点小记
一: 团队合作避免JS冲突 脚本中的变量随时存在冲突的风险, 1. 解决办法---用匿名函数将脚本包起来,让变量的作用域控制在匿名函数之内 如: <script type="tex ...
- 学习ThinkPHP笔记
学习ThinkPHP笔记 TP的模块化设计 名称 描述 应用 基于同一个入口文件访问的项目我们称之为一个应用. 模块 一个应用下面可以包含多个模块,每个模块在应用目录下面都是一个独立的子目录. 控制器 ...
- SQL 集合例子
IF OBJECT_ID('tempdb..#Purchase', 'U') IS NOT NULL DROP TABLE #Purchase; CREATE TABLE #Purchase ( Pu ...
- Magento2开发教程 - 如何向数据库添加新表
Magento 2具有特殊的机制,允许你创建数据库表,修改现有的,甚至添加一些数据到他们(如安装数据,已被添加在模块安装). 这种机制允许这些变化可以在不同的设备之间传输. 关键的概念是,而不是做你能 ...
- 使用<% =Type%>获取后台值时报错:控件包含代码块(即 <% ... %>),因此无法修改控件集合。
<% =Type%>不能放在runat="server"的标签中,删掉runat="server"之后dev的控件回调第一次发生时会刷新页面,有ru ...