目录:Django其他篇

01:Django基础篇

02:Django进阶篇

03:Django数据库操作--->Model

04: Form 验证用户数据 & 生成html

05:ModelForm 数据验证 & 生成html & 数据库操作

06: Django Admin

07: Django 学习补充

目录:

1.1 ModelForm作用及基本使用返回顶部

  1、form 作用

      1功能1  验证

      2功能2  生成html标签(默认功能:保留上次提交的值)

      3、功能3:  数据操作

      4、功能4: HTML Form提交保留上次提交数据

      5、功能5: 初始化页面显示内容

  2、form使用原则

      1、 新url方式操作(一定要用form方式生成html,避免提交刷新页面,丢失当前页面中填的值)

      2、 发Ajax请求时可以不用form生成html标签,仅用form做验证,因为ajax请求本身不刷新页面,不必担心填

           的值会丢失,当然使用form生成html也是可以的

1.2 Meta中定义字段验证规则返回顶部

    注意: 导入模块名(fields、widgets)和字段名重复,所以导入时要起个别名。

from django import forms
from django.forms import fields as Ffields
from django.forms import widgets as Fwidgets
class UserInfoModelForm(forms.ModelForm): is_rmb = Ffields.CharField(widget=Fwidgets.CheckboxInput()) class Meta:
model = models.UserInfo
fields = '__all__'
# fields = ['username','email']
# exclude = ['username']
labels = {
'username': '用户名',
'email': '邮箱',
}
help_texts = {
'username': '...'
}
widgets = {
'username': Fwidgets.Textarea(attrs={'class': 'c1'})
}
error_messages = {
'__all__':{ # 整体错误信息 },
'email': {
'required': '邮箱不能为空',
'invalid': '邮箱格式错误..',
}
}
field_classes = { # 定义字段的类是什么
# 'email': Ffields.URLField # 这里只能填类,加上括号就是对象了。
} # localized_fields=('ctime',) # 哪些字段做本地化

Meta中可以定义的字段类型

1.3 ModelForm应用:编辑默认选中 及 提交自动保存返回顶部

  1、所有文件

from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index/', views.index),
url(r'^user_list/', views.user_list),
url(r'^user_edit/(?P<nid>\d+)/', views.user_edit),
]

urls.py 路由系统

from django.db import models

class UserType(models.Model):
caption = models.CharField(max_length=32)
def __str__(self):
return self.caption class UserInfo(models.Model):
username = models.CharField(max_length=32)
email = models.EmailField()
user_type = models.ForeignKey(to='UserType', to_field='id')

models.py 定义表

from django.shortcuts import render,HttpResponse
from app01 import models
from app01.forms import UserInfoModelForm #1、创建UserInfo表中数据
def index(request):
if request.method == 'GET':
obj = UserInfoModelForm()
return render(request,'index.html',{'obj':obj})
elif request.method == 'POST':
obj = UserInfoModelForm(request.POST)
if obj.is_valid():
obj.save()
return render(request,'index.html',{'obj':obj}) #2、展示UserInfo表中数据
def user_list(request):
li = models.UserInfo.objects.all().select_related('user_type')
return render(request,'user_list.html',{'li':li}) #3、编辑默认选中 & 提交自动保存
def user_edit(request,nid):
if request.method == 'GET':
user_obj = models.UserInfo.objects.filter(id=nid).first()
mf = UserInfoModelForm(instance=user_obj) #只用传入instance点击编辑时就会默认选中
return render(request,'user_edit.html',{'mf':mf,'nid':nid})
elif request.method == 'POST': #ModelForm修改
user_obj = models.UserInfo.objects.filter(id=nid).first() # 如果这里没有传入 instance=user_obj就会变成ModelForm添加
mf = UserInfoModelForm(request.POST,instance=user_obj) #修改后数据要传递进去
if mf.is_valid():
mf.save()
else:
print(mf.errors.as_json())
return render(request,'user_edit.html',{'mf':mf,'nid':nid}) #################### 自动生成UserType 和 UserInfo 表中的数据 ############## usertype_list = [
{'caption':'python_group'},
{'caption':'linux_group'},
] userinfo_list = [
{'username':'zhangsan','email':'zhangsan@qq.com','user_type_id':1,},
{'username':'lisi','email':'lisi@qq.com','user_type_id':1,},
{'username':'wangwu','email':'wangwu@qq.com','user_type_id':1,},
] '''
for u_type in usertype_list:
models.UserType.objects.create(**u_type) for userinfo in userinfo_list:
models.UserInfo.objects.create(**userinfo)
'''

views.py 视图函数

from django.shortcuts import render,HttpResponse
from django import forms # 在ModelForm中有插件名widgets,所以这里引入插件时要取别名,否则报错
from django.forms import fields as Ffields
from django.forms import widgets as Fwidgets
from app01 import models class UserInfoModelForm(forms.ModelForm):
extraField = Ffields.CharField( widget=Fwidgets.CheckboxInput() ) #ModelForm中可以自定制额外字段
class Meta:
model = models.UserInfo #model指定关联那个类
fields = '__all__' labels = {
'username':'用户名',
'email':'邮箱',
} help_texts = {
'username':'username字段提示信息'
} widgets = {
'username':Fwidgets.Textarea(attrs={'class':'c1',})
} error_messages = {
'__all__':{}, #定义整体的错误信息
'email':{
'required':'邮箱不能为空',
'invalid':'邮箱格式错误',
}
} field_classes = {
# 'email':Ffields.URLField #改变字段格式为url
} localized_fields=('birth_date',)

forms.py 数据验证规则

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/index/" method="POST">
{% csrf_token %}
<p>{{ obj.username.label }}: {{ obj.username }} {{ obj.errors.username.0 }}</p>
<p>{{ obj.email.label }}: {{ obj.email }} {{ obj.errors.email.0 }}</p>
<p>{{ obj.user_type.label }}: {{ obj.user_type }} {{ obj.errors.user_type.0 }}</p>
<p>{{ obj.extraField.label }}: {{ obj.extraField }} {{ obj.errors.extraField.0 }}</p> <input type="submit" value="提交">
</form>
</body>
</html>

index.html生成html 创建数据

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<ul>
{% for row in li %}
<li>{{ row.username }}-{{ row.user_type.caption }}
<a href="/user_edit/{{ row.id }}/">编辑</a></li>
{% endfor %}
</ul>
</body>
</html>

user_list.html 展示数据

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="POST" action="/user_edit/{{ nid }}/">
{% csrf_token %}
{{ mf.as_p }}
<input type="submit" value="提交">
</form>
</body>
</html>

user_edit.html 编辑数据

   2、说明

      1. http://127.0.0.1:8000/index/  页面用来新建用户(在views.py中也有批量创建的for循环)

      2. http://127.0.0.1:8000/user_list/ 页面用来展示已创建用户,当点击编辑是会携带对应用户的id,已gett请求提交给user_edit

      3. http://127.0.0.1:8000/user_edit/1/ 这个路径携带有需要修改的用户id,实现编辑默认选中 及 提交自动保存

1.4 MordelForm中生成html & 数据验证 常用方法返回顶部

  1、生成HTML常用语法

      1、 obj.user.label                     标签显示内容(如:用户名)
            obj.user.label_tag

      2、 obj.user                            自动生成一个input标签,这种表自动保留上一次提交的数据功能

      3、 obj.errors.user.0              获取字段错误信息(提取到user字段)
            obj.errors                          所有字段错误信息的html字符串
            obj.user.errors                 错误信息(返回html标签)<ul class="errorlist"><li>用户名不能为空</li></ul>

      4、 obj.email.help_text          获取提示帮助信息(必须输入邮箱格式)

  4、ModelForm对象数据验证

    1. 用于验证

        model_form_obj = XXOOModelForm(request.POST)           # 将POST中提交的所有数据传给处理类(类中做校验)
        model_form_obj.is_valid()                                                # 类中对输入信息校验结果,符合返回True,否则返回False
        model_form_obj.clean()                                                   # 用户POST中所有正确信息,格式就是字典
        model_form_obj.cleaned_data

        model_form_obj.errors.as_json()                                     # 错误信息转换成json格式
        model_form_obj.errors                                                       # 所有错误信息的html字符串(ul li格式)

    2. 用于创建保存

        # 默认保存多对多
        obj = form.save(commit=True)

        # 不做任何操作,内部定义 save_m2m(用于保存多对多)
        obj = form.save(commit=False)
        obj.save()                                                 # 保存单表信息
        obj.save_m2m()                                       # 保存关联多对多信息

    4、新建数据 、修改数据、默认选中

        UserInfoModelForm(request.POST,instance=user_obj)           # 修改新旧数据都需要提交

        UserInfoModelForm(request.POST)                                        # 新建只需提交request.POST数据

        UserInfoModelForm(instance=user_obj)                                 # 只用传入instance点击编辑时就会默认选中 

    5. 验证执行过程
        is_valid -> full_clean -> 钩子 -> 整体错误

def clean_字段名(self):
# 可以抛出异常
# from django.core.exceptions import ValidationError
return "新值"

定义字段钩子

1.5 ModelForm验证规则中的内置钩子返回顶部

  1. from验证经历的顺序(搜索:Form and field validation

       验证执行过程:  is_valid -> full_clean -> 钩子 -> 整体错误

      1、拿到字段:用户发送一堆数据,根据form循环,拿到第一个字段

      2、正则匹配:先进行fields默认正则表达式判断,然后进行自定的正则表达式判断(如果有)

      3、字段钩子函数:然后执行字段的钩子函数,接着进行第二个字段,然后是第二个字段钩子函数...

      4、clean钩子函数:字段钩子函数执行完了再执行clean钩子函数进行整体验证

      5、_post_clean:     最后执行_post_clean钩子做其他验证

  2、 form验证的错误信息存放位置

      1、字段钩子错误信息放到对应的字段中 (obj.error中对应的字段字典)

      2、整体错误信息会放到 {"__all__":[],}中等价于{'NON_FIELD_ERRORS':[],} (如:执行clean)

  3、forms.py文件中使用这三种钩子

from django import forms
from django.forms import fields as Ffields
from django.forms import widgets as Fwidgets
from app01 import models
from django.core.exceptions import ValidationError class UserInfoModelForm(forms.ModelForm):
extraField = Ffields.CharField( widget=Fwidgets.CheckboxInput() ) #ModelForm中可以自定制额外字段
class Meta:
model = models.User #model指定关联那个类
fields = '__all__' labels = {
'name':'用户名',
'pwd':'密码',
} #1 clean_字段名 是字段钩子(每个字段都有对应的这个钩子):如判断:“用户名已存在”
def clean_user(self):
# self.cleand_data['user']是用户提交的数据'
c = models.User.objects.filter(name=self.cleand_data['user']).count()
if not c:
return self.cleand_data['user'] #必须要有返回值
else:
raise ValidationError('用户名已存在',code='xxx') #2 clean钩子对整体验证:如判断“用户名或密码错误”
def clean(self):
c = models.User.objects.filter(
name=self.cleand_data['user'],
pwd=self.cleand_data['pwd']).count()
if c:
return self.cleand_data #正确的值必须return回去
else:
raise ValidationError('用户名或密码错误') #3 在这里可以做 其他验证
def _post_clean(self):
pass

forms.py文件中使用这三种钩子

1.6 使用type动态生成ModelForm类进行数据验证、生成html返回顶部

from django.db import models

class User(models.Model):
username = models.CharField(max_length=32)
def __str__(self):
return self.username def default_form_validation(self):
''' 每个class_admin都可以重写这个方法来对整体验证'''

models.py创建表

from django.shortcuts import render
from app01 import models
from app01.forms import create_model_form def login(request):
model_form_class = create_model_form(request,models.User) form_obj = model_form_class() if request.method == 'POST':
obj = models.User.objects.get(id=1)
form_obj = model_form_class(instance=obj)
form_obj = model_form_class(request.POST,instance=obj)
if form_obj.is_valid():
form_obj.save()
else:
print('errors',form_obj.errors)
return render(request, 'loin.html',{'form_obj':form_obj})

views.py视图函数

from django.forms import ModelForm,ValidationError
from app01 import models def create_model_form(request,admin_class):
def __new__(cls,*args,**kwargs): # 重写ModelForm的__new__方法
'''
作用1--> 添加字段样式: class="form-control"
作用2--> 添加字段钩子: clean_字段名
'''
for field_name, field_obj in cls.base_fields.items():
# field_name : 字段名称,比如 "username"
# field_obj : 定义字段样式的类
field_obj.widget.attrs['class'] = "form-control" # 给所有字段添加样式:class="form-control" if hasattr(admin_class, "clean_%s" % field_name): # clean_字段名 是字段钩子(每个字段都有对应的这个钩子)
field_clean_func = getattr(admin_class, "clean_%s" % field_name)
setattr(cls, "clean_%s" % field_name, field_clean_func)
return ModelForm.__new__(cls) # 调用一下ModelForm的__new__方法否则不往下走 def default_clean(self): # 重写ModelForm的 default_clean 方法
'''添加默认钩子'''
error_list = [] # 在这个cleaned方法中定义一个允许用户自己定义的方法做验证
response = admin_class.default_form_validation(self)
if response:
error_list.append(response) if error_list:
raise ValidationError(error_list) class Meta: # ModelForm中使用Meta类进行条件过滤
model = models.User # model指定关联那个类
fields = "__all__" # 对那些字段过滤 labels = {
'username': '用户名',
} attrs = {'Meta':Meta} _model_form_class = type("DynamicModelForm",(ModelForm,),attrs) #创建类并设置Meta属性
setattr(_model_form_class,"__new__",__new__) #动态将__new__函数添加到类中
setattr(_model_form_class,'clean',default_clean) #动态将_default_clean__函数添加到类中 return _model_form_class

froms.py动态生成ModelForm类

1.7 ModelForm实例:不使用ModelForm生成html、并用ajax提交显示错误信息返回顶部

  相关知识点:

      1、不使用ModelForm生成html
      2、使用ajax提交数据,所以无法使用obj.errors.xxx 在前端显示错误信息
      3、使用json序列化ModelForm验证的错误信息
      4、使用ajax将错误信息放到对应位置

from django.shortcuts import render,HttpResponse
from django.utils import timezone
from django.core.exceptions import ValidationError import hashlib
import json from app01.models import User
from app01.forms import RegisterFrm class JsonCustomEncoder(json.JSONEncoder):
def default(self, field):
if isinstance(field, ValidationError):
return {'code':field.code,'messages':field.messages}
else:
return json.JSONEncoder.default(self, field) def register(request):
if request.method == 'POST':
if request.method == 'POST':
ret = {'status': False, 'error': None, 'data': None}
obj = RegisterFrm(request.POST)
if obj.is_valid():
cd = obj.cleaned_data
new_user = obj.save(commit=False) # 将密码md5加密后再存到数据库中
password2 = cd.get("password2")
m = hashlib.md5()
m.update(password2.encode())
new_user.password = m.hexdigest()
new_user.save()
ret['status']=True
return HttpResponse(json.dumps(ret))
else:
ret['error'] = obj.errors.as_data() # as_json() 返回的是字符串
request = json.dumps(ret, cls=JsonCustomEncoder)
return HttpResponse(request)
obj = RegisterFrm()
return render(request,'register.html',{'obj':obj}) # 登陆 : 这里没有做登录界面只有验证密码的函数
def login(request):
if request.method == 'POST':
login_name = request.POST.get("login_name")
password = request.POST.get("password")
if login_name and password:
# 将密码转md5
m = hashlib.md5()
m.update(password.encode())
password_md5 = m.hexdigest()
# 获取用户对象
user = User.objects.filter(login_name=login_name, password=password_md5).first()
if user:
print('用户密码正确')

views.py

from django.db import models

class User(models.Model):
login_name = models.CharField(max_length=32,unique=True,verbose_name="用户名",error_messages={'unique':"用户名已占用"})
password = models.CharField(max_length=32)
email = models.EmailField(unique=True,error_messages={'unique':'邮箱已注册'})
def __str__(self):
return self.login_name

models.py

from django import forms
from django.forms import fields
from app01.models import User class RegisterFrm(forms.ModelForm):
login_name = forms.CharField(
required=True,
error_messages={
'required': '用户名不能为空',
})
email = forms.EmailField(
error_messages={
'required': '邮箱不能为空',
'invalid':'邮箱格式错误'
})
password = forms.CharField(
widget=forms.PasswordInput,
label="密码",
error_messages={
'required': '密码不能为空',
})
password2 = forms.CharField(
widget=forms.PasswordInput,
label="确认密码",
error_messages={
'required': '确认密码不能为空',
}) class Meta:
model = User
fields = ("login_name", "password", "email") def clean_login_name(self):
"""login_name里不允许有空格"""
cd = self.cleaned_data
login_name = cd.get("login_name").strip()
if " " in login_name:
raise forms.ValidationError("用户名不能有空格")
return login_name def clean_password2(self):
"""两次密码是否一致"""
cd = self.cleaned_data
if cd['password'] != cd['password2']:
raise forms.ValidationError('确认密码不一致')
return cd['password2']

forms.py

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class="reg_frm fl">
<h1>注册{{ obj.errors }}</h1>
<form id="register_frm">
<table>
<tr>
<th>用户名</th>
<td><input type="text" id="login_name" name="login_name"></td>
<td class="tips">{{ obj.login_name.errors.0 }}</td>
</tr>
<tr>
<th>邮箱</th>
<td><input type="email" id="email" name="email"></td>
<td class="tips">{{ obj.email.errors.0 }}</td>
</tr>
<tr>
<th>密码</th>
<td><input id="password" type="password" name="password" autocomplete="off" minlength="3"></td>
<td class="tips">{{ obj.password.errors.0 }}</td>
</tr>
<tr>
<th>确认密码</th>
<td><input id="password2" type="password" name="password2" autocomplete="off" minlength="3"></td>
<td class="tips"></td>
</tr>
</table>
<p><input type="button" value="ajax提交" onclick="ajaxSubmit();"></p>
</form>
</div>
<script src="/static/jquery-1.12.4.min.js"></script>
<script>
function ajaxSubmit() {
$.ajax({
url:'/register/',
data:$('#register_frm').serialize(),
type:'POST',
dataType:'json',
success:function(arg){ //服务端返回的是字符串格式
if(arg.status==true){
console.log('成功创建用户后的操作')
}else {
var check_list = {
'login_name':'用户名',
'email':'邮箱',
'password':'密码',
'password2':'确认密码'
};
for(var key in check_list){
$('#'+key).parent().parent().find('.tips').text('');
var err_val = "arg.error." + key +"[0].messages";
try{
var err = eval(err_val);
$('#'+key).parent().parent().find('.tips').text(err)
}catch (err){
console.log(err.message);
}
}
}
}
})
}
</script>
</body>
</html>

register.html

05:ModelForm 数据验证 & 生成html & 数据库操作的更多相关文章

  1. 手把手封装数据层之DataUtil数据库操作的封装

    上一篇我们写完了数据库连接的封装 没有看的请移步上一篇关于数据库连接的内容 这次我们讲数据库操作的封装.数据库的操作就是增删改查:心再大一点就可以直接分为查询和其他. 因为查询是有返回对象的,而其他都 ...

  2. Android数据读取之Sqlite数据库操作

    咱们书接上文,继续来说说Android数据读取,这回,我们要讲的是Sqlite数据库的相关操作.以一个实例开始吧: 首先,上图,看看做成后的效果: 大概描述:类似于浏览器的收藏夹,网站名称,网站地址, ...

  3. android菜鸟学习笔记20----Android数据存储(四))Android数据库操作

    Android内置了一个名为SQLite的关系型数据库,这是一款轻量型的数据库,操作十分简便.SQLite与别的数据库不同的是,它没有数据类型.可以保存任何类型的数据到你所想要保存的任何表的任何列中. ...

  4. Effective C++ .05 一些不自动生成copy assigment操作的情况

    主要讲了 1. 一般情况下编译器会为类创建默认的构造函数,拷贝构造函数和copy assignment函数 2. 执行默认的拷贝构造/copy assignment函数时,如果成员有自己的拷贝构造/c ...

  5. 03: Django Model数据库操作

    目录:Django其他篇 01:Django基础篇 02:Django进阶篇 03:Django数据库操作--->Model 04: Form 验证用户数据 & 生成html 05:Mo ...

  6. python 学习笔记十六 django深入学习一 路由系统,模板,admin,数据库操作

    django 请求流程图 django 路由系统 在django中我们可以通过定义urls,让不同的url路由到不同的处理函数 from . import views urlpatterns = [ ...

  7. 结合java的反射和泛型性质简化JDBC和相应的同步等服务器数据库操作代码

    github地址:https://github.com/hzphzp/HeartTrace_Server 我们的服务器端数据库并没有用sqllite, 而是直接用mysql,并且用JDBC直接进行操作 ...

  8. PHP 生成 MySql 数据库字典

    项目说明 通过配置 MySql 数据库信息,使用 PHP 生成数据表字典可以输出在当前页面,可以生成文件保存在指定位置,也可以下载格式支持网页HTML格式.CSV格式(Excel 读取).ZIP压缩格 ...

  9. JSP中的数据库操作,MySQL基础操作(一)

    一.JDBC JDBC(java data base concectivity),是一种用于执行SQL语句的java API,可以为多种关系库提供统一访问. 通常使用JDBC完成以下操作: 1)同数据 ...

随机推荐

  1. 2018-2019-2 20165330《网络对抗技术》Exp6 信息搜集与漏洞扫描

    目录 基础问题 相关知识 实验目的 实验内容 实验步骤 实验总结与体会 实验目的 掌握信息搜集的最基础技能与常用工具的使用方法. 返回目录 实验内容 各种搜索技巧的应用 使用搜索引擎 搜索网址目录结构 ...

  2. HDFS架构详解-非官档

    Namenode 1.namenode是一个中心服务器,单一节点(简化系统的设计和实现),负责管理文件系统的命名空间(namespace)以及客户端对文件的访问. 2.文件操作:namenode负责对 ...

  3. Python开发【笔记】:关于子线程(子进程)与主线程(主进程)的关联

    前言: 主要分析下面的问题: 主线程启线程  主线程执行完毕,会关闭子线程吗? 子线程启线程  主线程执行完毕,会结束吗? 主进程启动进程,主进程执行完毕,会怎样? 子进程启动进程,进程执行完毕,又会 ...

  4. 洛谷P3599 Koishi Loves Construction 构造

    正解:构造 解题报告: 传送门! 这题俩问嘛,就分成两个问题港QwQ 就按顺序趴,先港第一问QwQ 首先要发现,n在膜n意义下就是0嘛 那作为前缀和的话显然它就只能放在第一个 然后再想下,发现,如果n ...

  5. 洛谷P1967 货车运输 [noip2013] 图论

    正解:kruskal+LCA 解题报告: 哇真实心痛了...明明都没多少时间了我居然耗了一个上午+一个中午在上面?哭死辽我QAQ果然菜是原罪QAQ 然后这题,我先港下60pts做法趴?话说其实我觉得我 ...

  6. 10个实用的Django建议(转)

    前言:随着Django1.4第二个候选版的发布,虽然还不支持Python3,但Django团队已经在着手计划中,据官方博客所说, Django1.5将会试验性的支持python3.Django 作为一 ...

  7. 【JMeter】如何录制创建及得到曲线图

    前段时间公司需要对服务器进行压力测试,包括登录前的页面和登录后的页面,主要目的是测试负载均衡的实现效果.不知道是不是因为Jmeter不如loadRunner火爆还是什么,网上关于Jmeter的资料有很 ...

  8. 15 jmeter分布式性能测试

    背景由于jmeter本身的瓶颈,当需要模拟数以千计的并发用户时,使用单台机器模拟所有的并发用户就有些力不从心,甚至还会引起Java内存溢出的错误.要解决这个问题,可以使用分布式测试,运行多台机器运用所 ...

  9. sdut2193救基友记3(三维)

    http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2193 救基友记3 Time Limit: 10 ...

  10. Hat's Fibonacci

    http://acm.hdu.edu.cn/showproblem.php?pid=1250 大数斐波那契 %08d是什么东西,为什么我用flag交不上,唉,不刷大数了,没劲.暑假再讲. 就是交不上 ...