Django中ModelForm详解
modelform的常用配置#
from django import forms
from django.forms import widgets as wid #因为重名,所以起个别名
class ProjectForm(forms.ModelForm):
class Meta:
model = models.Project #对应的Model中的类
# fields = "__all__" #字段,如果是__all__,就是表示列出所有的字段
# fileds = ['project_status','project_name'] #列出的字段
exclude = ['project_status'] # 排除哪些字段
exclude = None #排除的字段
labels = None #提示信息
help_texts = None #帮助提示信息
widgets = None #自定义插件
error_messages = None #自定义错误信息
#######################配置################################
#labels,自定义在前端显示的名字
labels = {
"project_name": "项目名称",
"project_detail": "项目描述",
}
#显示的错误信息
error_messages = {
"project_name": {"required": "不能为空"},
"project_detail": {"required": "不能为空"}
}
#前端显示的input框
widgets = {
"project_name": wid.TextInput(attrs={"class": "form-control"}), #还可以自定义属性
"project_detail": wid.Textarea(attrs={"class": "form-control"})
}
引用#
创建时引用#
html文件
<form action="" method="post" novalidate>
{% csrf_token %}
{% for foo in form %}
<div class="form-group">
<label for="">{{ foo.label }}</label>
{{ foo }}
<span style="color: red">{{ foo.errors.0 }}</span>
</div>
{% endfor %}
<input type="submit" value="提交" class="btn btn-default">
</form>
views.py
def project_add(request):
""" 新增项目记录 """
if request.method == 'POST':
form_obj = ProjectForm(request.POST)
if form_obj.is_valid():
form_obj.save()
return redirect('/index/')
else:
return render(request, 'project_add.html', {'form': form_obj})
else:
form_obj = ProjectForm()
return render(request, 'project_add.html', {"form": form_obj})
编辑时的用法#
html文件不变。
需要在使用modelform时使用instance传递数据,进行更新。
views.py
def project_update(request, pk):
""" 更新项目 """
model_obj = models.Project.objects.filter(pk=pk).first()
if request.method == 'POST':
form_obj = ProjectForm(request.POST, instance=model_obj)
if form_obj.is_valid():
form_obj.save()
return redirect('/index/')
else:
return render(request, 'update_project.html', {'form': form_obj})
else:
form_obj = ProjectForm(instance=model_obj)
return render(request, 'update_project.html', {"form": form_obj})
路由别忘了配置pk
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index/', views.index, name='index'),
url(r'^project_update/(?P<pk>\d+)$', views.project_update, name='project_update'),
]
自定义标签#
适合一些特殊的标签,比如日期标签,下面是form设置。
法1
from django import forms
from django.forms import widgets as wid
from app01 import models
class ApiForm(forms.ModelForm):
# 自定义标签
api_start_time = forms.DateField(label="开始时间", widget=wid.DateInput(attrs={"class": "form-control", 'type': "date"}))
api_stop_time = forms.DateField(label="结束时间",widget=wid.DateInput(attrs={"class": "form-control", 'type': "date"}))
class Meta:
model = models.API
fields = "__all__"
# exclude = ['project_status'] # 排除哪些字段
# labels = {
# "project_name": "项目名称",
# "project_detail": "项目描述",
# }
error_messages = {
"api_title": {"required": "不能为空"},
"api_desc": {"required": "不能为空"}
}
widgets = {
"api_title": wid.TextInput(attrs={"class": "form-control"}),
"api_desc": wid.Textarea(attrs={"class": "form-control"})
}
##如:表中没有的字段想在前端显示? 如登录时的确认密码,表中没有这个字段,但前端是要显示的,可以这么写加上这个自定义字段
confirm_password = forms.CharField(
label='确认密码',
widget=forms.PasswordInput(), #这里和写wid.PasswordInput()一样,看源码导入的是同一个文件
min_length=6,
max_length=16,
error_messages={
"min_length": "重复密码长度不能小于8位",
"max_length": "重复密码长度不能大于16位"
},
)
法2
from django.forms import ModelForm
from django import forms
from django.forms import widgets as wid
from app01 import models
class ApiForm(ModelForm):
class Meta:
model = models.API
fields = "__all__"
bootstrapClass_filter = ['api_start_time', 'api_stop_time']
api_start_time= forms.DateField(label="开始时间",
widget=wid.DateInput(attrs={"class": "form-control", 'type': "date"}))
api_stop_time= forms.DateField(label="结束时间", widget=wid.DateInput(attrs={"class": "form-control", 'type': "date"}))
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for name, field in self.fields.items():
if name in self.bootstrapClass_filter:
continue
old_class = field.widget.attrs.get('class', "")
field.widget.attrs['class'] = '{} form-control'.format(old_class)
field.widget.attrs['placeholder'] = '请输入%s' % (field.label,)
数据库:
class API(models.Model):
""" 接口表 """
api_title = models.CharField(max_length=32, verbose_name='接口名称')
api_desc = models.CharField(max_length=128, verbose_name='接口描述')
api_start_time = models.DateField(auto_now_add=True)
api_stop_time = models.DateField(auto_now_add=True)
def __str__(self):
return self.api_title
def xxoo(self): # 自定义字段
if self.case_set.count():
a = "%s%% " % (self.case_set.filter(case_pass_status=1).count() / self.case_set.count() * 100)
return a
else:
return 0
编辑数据:
如果不用ModelForm,编辑的时候得显示之前的数据吧,还得挨个取一遍值,如果ModelForm,只需要加一个instance=obj(obj是要修改的数据库的一条数据的对象)就可以得到同样的效果。
保存的时候要注意,一定要注意有这个对象(instance=obj),否则不知道更新哪一个数据。
代码示例:
使用ModelForm编辑数据
对于验证规则,很多浏览器都比较智能,会自动帮我们做一些验证,可以在form表单上加 novalidate 属性就可以不让浏览器为我们做验证
ModelForm还支持所有form的功能,比如钩子,所以我们就可以通过钩子来自定义验证规则
写法和forms的写法一样:
class AuthorForm(forms.ModelForm):
class Meta:
model = API
fields = ('api_title')
def clean_api_title(self):
if ...
return self.clean_data['api_title'] #如果校验正常,正常返回数据
else:
raise ValidationError(‘sdgsadga’)
...
作者: 听雨危楼
出处:https://www.cnblogs.com/Neeo/articles/10437793.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
仰望星空,脚踏实地