Django11-ModelForm
一、定义ModelForm类
# 创建部门表单校验
class DepartmentForm(forms.ModelForm):
class Meta:
model = models.Department #关联到Models中的表名Department
fields = '__all__' #获取Department表中的所有对象,也可以写成列表['depName','depDes'],指定要获取的对象,而且是有顺序的
labels = {
'depName': '部门名称',
'depDes': '职责描述',
}
widgets = { #设置插件,type类型和类名等属性
'depName': forms.TextInput(attrs={'class': 'form-control','placeholder':'请输入部门名称'}),
'depDes': forms.TextInput(attrs={'class': 'form-control','placeholder':'请输入部门职责描述'}),
}
class Meta:下常用参数:
model = models.Department # 对应的Model中的类
fields = "__all__" # 字段,如果是__all__,就是表示列出所有的字段,也可以写成列表['title','price'],指定要获取的对象
exclude = None # 排除的字段
labels = None # 提示信息
help_texts = None # 帮助提示信息
widgets = None # 自定义插件,form组件里是widget,ModelForm组件里是widgets
error_messages = None # 自定义错误信息
其中label属性可以不在ModelForm这里面写,也可以在models.py中的Depart表中各个对象定义verbose_name属性值,用于非ForeignKey对象,
推荐这种写法,在Admin系统中也可以显示这里定义的verbose_name值
class Depart(models.Model):
depName = models.TextField(max_length=32, verbose_name='部门名称')
depDes = models.TextField(max_length=64, black=True, null=True, verbose_name='职责描述')
二、批量添加样式
可通过重写ModelForm类的init方法来实现。
# 创建部门表单校验
class DepartmentForm(forms.ModelForm):
depName = forms.TextField(validators=[],) #如果depName字段存在,就代表重写这个字段
count = forms.TextField(validators=[],) #如果count字段不存在,就代表新增这个字段,models文件中不存在这个字段
class Meta:
model = models.Department #model和fields都是固定写法,不能写
fields = '__all__'
labels = {
'depName': '部门名称',
'depDes': '职责描述',
}
widgets = {
'depName': forms.TextInput(attrs={'placeholder':'请输入部门名称'}),
'depDes': forms.TextInput(attrs={'placeholder':'请输入部门职责描述'}),
'purchase_date': forms.widgets.DateInput(attrs={'type': 'date'}),
'expiration_date': forms.widgets.DateInput(attrs={'type': 'date'}), }
error_messages = { #这里的error_messages只能写默认存在的校验字段
'depName':{
'required':'不能为空'
}
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self.fields.values():
field.widget.attrs.update({'class': 'form-control'}) class DepartAdd(View):
def get(self, request):
form_obj = DepartmentForm()
return render(request, 'departadd.html', {'form_obj': form_obj}) def post(self, request):
form_obj = DepartmentForm(request.POST)
print(form_obj)
if form_obj.is_valid():
# models.Department.objects.create(**form_obj.cleaned_data)
form_obj.save() #直接save()方法就可以保存
return redirect(reverse('departList'))
三、部门添加、修改例子(FVB版)
部门添加
def depart_add(request):
form_obj = departForm.DepartForm()
if request.method == 'POST':
form_obj = departForm.DepartForm(request.POST)
if form_obj.is_valid():
form_obj.save()
return redirect(reverse('depart_list'))
return render(request, 'depart/depart_add.html', {'form_obj': form_obj})
部门修改
def depart_edit(request, pk):
form_edit = models.Depart.objects.filter(pk=pk).first()
form_obj = departForm.DepartForm(instance=form_edit)
if request.method == 'POST':
form_obj = departForm.DepartForm(request.POST, instance=form_edit) #这里要将当前对象作为一个实例传给ModelForm
# 如果没有修改,则不需要校验
depart_name_new = request.POST.get('depart_name', None)
if form_edit.depart_name == depart_name_new:
# 部门描述不需要校验,直接更新保存
form_edit.depart_desc = request.POST.get('depart_desc', None)
form_edit.save()
return redirect(reverse('depart_list'))
# 如果修改了值,就调用DepartForm校验,注意用instance表示将当前对象传给Modelform校验,模板中字段仍然可以自动生成
elif form_obj.is_valid():
form_obj.save()
return redirect(reverse('depart_list'))
return render(request, 'depart/depart_edit.html', {'form_edit': form_edit, 'form_obj': form_obj})
前端页面
展示页面depart_list.html
<table class="form-horizontal table table-bordered" style="margin-top: 10px">
<thead>
<tr>
<th>ID</th>
<th>用户名称</th>
<th>密码</th>
<th>所属部门</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for user in user_all %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ user.username }}</td>
<td>{{ user.pwd }}</td>
{# <td>{{ user.depart.depart_name}}</td>#} #这里可以通过depart外键.depart_name来获取部门名称进行前端页面显示
<td>{{ user.depart }}</td> #也可以通过在models.py中给Depart类写__str__方法,这里就不需要用点方法了
<td>
<a href="{% url 'user_edit' user.pk %}"><i class="fa fa-edit fa-2x"></i></a>
<a class="del" del_obj="user" del_id="{{ user.pk }}"><i class="fa fa-trash-o fa-2x" style="cursor: pointer;"></i></a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
修改页面depart_edit.html
<form action="" method="post" class="form-horizontal">
{% csrf_token %}
<div class="form-group {% if form_obj.depName.errors %}has-error{% endif %}">
<label for="{{ form_obj.depName.id_for_label }}" class="col-lg-2 control-label">{{ form_obj.depName.label }}</label>
<div class="col-lg-6">
{{ form_obj.depName }}
</div>
<span class="help-block">{{ form_obj.errors.0 }}</span>
</div> bootstrape样式中使用has-error和help-block类渲染错误提示效果
models.py
from django.db import models # Create your models here.
class Depart(models.Model):
depart_name = models.CharField(max_length=32, verbose_name='部门名称')
depart_desc = models.CharField(max_length=64, verbose_name='部门描述') #通过写__str__方法,前端直接调用depart对象时就可以直接获取到depart_name的值了
def __str__(self):
return self.depart_name class User(models.Model):
username = models.CharField(max_length=32, verbose_name='用户名')
pwd = models.CharField(max_length=32, verbose_name='密码')
depart = models.ForeignKey(to='Depart', verbose_name='所属部门')
四、代码合并
1、depart_all.html模板代码合并
未合并写法,写了多个form-group,重复
<form action="" method="post" class="form-horizontal" novalidate>
{% csrf_token %}
<div class="form-group {% if form_obj.depart_name.errors %}has-error{% endif %}">
<label for="{{ form_obj.depart_name.id_for_label }}" class="col-lg-2 control-label">
{{ form_obj.depart_name.label }}
</label>
<div class="col-lg-6">
{{ form_obj.depart_name }}
<span class="help-block">{{ form_obj.depart_name.errors.0 }}</span>
</div>
</div> <div class="form-group {% if form_obj.depart_desc.errors %}has-error{% endif %}">
<label for="{{ form_obj.depart_desc.id_for_label}}" class="col-lg-2 control-label ">
{{ form_obj.depart_desc.label }}
</label>
<div class="col-lg-6">
{{ form_obj.depart_desc }}
<span class="help-block">{{ form_obj.depart_desc.errors.0 }}</span>
</div>
</div> <div class="form-group">
<div class="col-lg-10 col-lg-offset-2">
<button class="btn btn-primary">提交</button>
</div>
</div>
</form>
合并写法
<form action="" method="post" class="form-horizontal" novalidate>
{% csrf_token %} {#需要渲染多个form-group, 可以使用for循环避免重新编写,将form_obj.depart_name和form_obj.depart_desc改成field即可#}
{% for field in form_obj %}
<div class="form-group {% if field.errors %}has-error{% endif %}">
<label for="{{ field.id_for_label }}" class="col-lg-2 control-label">
{{ field.label }}
</label>
<div class="col-lg-6">
{{ field }}
<span class="help-block">{{ field.errors.0 }}</span>
</div>
</div>
{% endfor %} <div class="form-group">
<div class="col-lg-10 col-lg-offset-2">
<button class="btn btn-primary">提交</button>
</div>
</div>
</form>
2、views.py视图代码合并
未合并写法
urls.py
url(r'^user/add/$', user.user_add, name='user_add'),
url(r'^user/edit/(\d+)/$', user.user_edit, name='user_edit'), views.py
#用户添加函数
def user_add(request):
form_obj = userForm.UserForm()
if request.method == 'POST':
form_obj = userForm.UserForm(request.POST)
if form_obj.is_valid():
form_obj.save()
return redirect(reverse('user_list'))
return render(request, 'user/user_add.html', {'form_obj': form_obj}) #用户编辑函数
def user_edit(request, pk):
obj = models.User.objects.filter(pk=pk).first()
form_obj = userForm.UserForm(instance=obj)
if request.method == 'POST':
form_obj = userForm.UserForm(request.POST, instance=obj)
# 如果未修改原值,则不校验
if request.POST.get('username', None) == obj.username:
obj.pwd = request.POST.get('pwd', None)
obj.gender = request.POST.get('gender', None)
# depart不能直接保存为request.POST.get('depart',None),因为depart是一个外键,需要保存Depart的一个实例
obj.depart = models.Depart.objects.filter(pk=request.POST.get('depart', None)).first()
obj.save()
# 这里先创建用户的时候校验密码不能为空,但是修改用户时没有校验密码是否为空
return redirect(reverse('user_list'))
# 修改了原值,则进行校验
elif form_obj.is_valid():
form_obj.save()
return redirect(reverse('user_list'))
return render(request, 'user/user_edit.html', {'form_obj': form_obj})
将用户添加函数和用户编辑函数合并编写
将urls中函数方法统一写成user_change,在views中只需要写一个user_change函数包含用户添加和编辑功能。 urls.py
url(r'^user/add/$', user.user_change, name='user_add'),
url(r'^user/edit/(\d+)/$', user.user_change, name='user_edit'), views.py
由于用户添加和编辑函数逻辑相似,可以合并编写
区别就是编辑函数需要传入pk值,而添加函数不需要传入pk值,所以设置pk=None默认为空
其他代码基本相同 def user_change(request, pk=None):
#如果是添加方法,则obj为空
obj = models.User.objects.filter(pk=pk).first()
form_obj = userForm.UserForm(instance=obj)
if request.method == 'POST':
form_obj = userForm.UserForm(request.POST, instance=obj)
if obj:
# 如果未修改username原值,则不校验
if request.POST.get('username', None) == obj.username:
obj.pwd = Md5(request.POST.get('pwd', None)).md5
obj.gender = request.POST.get('gender', None)
# depart不能直接保存为request.POST.get('depart',None),因为depart是一个外键,需要保存Depart的一个实例
obj.depart = models.Depart.objects.filter(pk=request.POST.get('depart', None)).first()
obj.save()
# 这里先创建用户的时候校验密码不能为空,但是修改用户时没有校验密码是否为空
return redirect(reverse('user_list'))
# 修改了原值,则进行校验
elif form_obj.is_valid():
form_obj.save()
return redirect(reverse('user_list'))
return render(request, 'user/user_edit.html', {'form_obj': form_obj})
Django11-ModelForm的更多相关文章
- 【Django】--ModelForm组件
ModelForm a.class Meta: model,#对应Model的 fields=None,#字段 exclude=None,#排除字段 labels=None,#提示信息 help_te ...
- Django Form and Modelform Admin定义 高级查询)
Django的form表单一般具有两种功能 1. 验证输入 2.输入HTML ---------模板----------- from django import forms class BookFor ...
- Django ModelForm and Form
django表单系统中,所有的表单类都作为django.forms.Form的子类创建,包括ModelForm 关于django的表单系统,主要分两种 基于django.forms.Form 基于dj ...
- Django: ModelForm中Meta的fields等成员介绍
class MyForm(forms.ModelForm): realname = forms.CharField() phone = forms.CharField() class Meta: mo ...
- Django中ModelForm应用
Django中ModelForm的应用 在传统中Form提交的POST的数据在服务器端获取时将不得不一一获取并验证数据的可靠性,但是使用django提供的Form时可简化该过程并提供相应的验证,同时D ...
- Django中使用ModelForm实现Admin功能
接上一篇<Django中使用Bootstrap> ModelForm 可以将数据库中的信息展示在一个表中,因此我们在查询数据库信息时可以使用ModelForm在前端展示查询到的信息. 在上 ...
- django Modelform
前言: 为什么要用form去验证呢? 我们提交的是form表单,在看前端源码时如果检查到POST URL及我们提交的字段,如果没有验证我们是否可以直接POST数据到URL,后台并没有进行校验,直接处理 ...
- ModelForm
这是一个神奇的组件,通过名字我们可以看出来,这个组件的功能就是把model和form组合起来,对,你没猜错,相信自己的英语水平. 先来一个简单的例子来看一下这个东西怎么用: 比如我们的数据库中有这样一 ...
- Django的ModelForm组件
创建类 from django.forms import ModelForm from django.forms import widgets as wd from app01 import mode ...
- Django ModelForm修改默认的控件属性
Django 中利用ModelForm 可以快速地利用数据库对应的Model 子类来自动创建对应表单. 例如: from django.db import models from django.for ...
随机推荐
- Linux系统安装IonCube的方法详解教程
ioncube是业内优秀的php加密解密解决方案.和zend guard相比,ioncube具有如下优势: 1. 安全:zend guard的版本不是非常安全,网络上有破解使用zend,下面我们来看I ...
- 家人的健康和offer的取舍
记得2月份去Amazon面试的时候,小孩子正莫名的发烧,已经破纪录的连续烧了4天,到了6点面试完毕,面试官还试探性的问我还有没有什么要聊的,当时确实是没了心情,就想着回家看小病人,在回家的路上,暗暗的 ...
- 找出n之内的完全数, 并输出其因子
定义: 完全数:所有的真因子(即除了自身以外的约数)的和,恰好等于它本身.例如:第一个完全数是6,它有约数1.2.3.6,除去它本身6外,其余3个数相加,1+2+3=6.第二个完全数是28,它有约数1 ...
- 为什么以sys无法远程登录数据库
今天通过pl/sql连接一个数据库,普通用户能连接上,但是sys就连接不上,告诉我用户名密码错误.之前其实遇到过这个问题,然后就开始查找原因.整个过程记录如下,结果是扎心的,过程也不是完全都懂.记下来 ...
- Linux----------Openssh介绍以及用法
一.OpenSSH介绍 OpenSSH这一术语指系统中使用的Secure Shell软件的软件实施.用于在远程系统上安全运行shell.如果您在可提供ssh服务的远程Linux系统中拥有用户帐户,则s ...
- digital envelope routines:EVP_DecryptFinal_ex:wrong final block length问题原因分析
最近在做一个项目时,使用openssl中的aes进行加密和解密,使用相同的密钥但是出现下面的错误日志: 139868329146176:error:0606506D:digital envelope ...
- Networked Graphics: Building Networked Games and Virtual Environments (Anthony Steed / Manuel Fradinho Oliveira 著)
PART I GROUNDWORK CHAPTER 1 Introduction CHAPTER 2 One on One (101) CHAPTER 3 Overview of the Intern ...
- 如何让 KiCad EDA 5.1 不显示铺铜
如何让 KiCad EDA 5.1 不显示铺铜 在画板最后给 PCB 铺地,铺地结束后检查然后发板出去打板. 板子回来焊接,调试时发现有问题,边调边改线路,打开 KiCad 一看满屏的铜皮,怎么改呀? ...
- 2019.4.24 一题(CF 809E)——推式子+虚树
题目:http://codeforces.com/contest/809/problem/E
- 关于让simulink中display组件显示二进制的方法
关于让simulink中display组件显示二进制的方法 1.首先需要配置gateway out模块,勾选propagate data type to output 2.配置display模块 fo ...