简介

Model + Form ==> ModelForm。model和form的结合体,所以有以下功能:

  • 验证
  • 数据库操作

Form回顾

models.py

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

forms.py

from django import forms
from django.forms import fields class UserInfoForm(forms.Form):
# username = models.CharField(max_length=32) <-- models
username = fields.CharField(max_length=32)
# email = models.EmailField() <-- models
email = fields.EmailField()
# user_type = models.ForeignKey(to='UserType',to_field='id') <-- models
user_type = fields.ChoiceField(
choices=models.UserType.objects.values_list('id','caption')
) # 下面的操作是让数据在网页上实时更新。
def __init__(self, *args, **kwargs):
super(UserInfoForm,self).__init__(*args, **kwargs)
self.fields['user_type'].choices = models.UserType.objects.values_list('id','caption')

index.html

<body>
<form action="/index/" method="POST" novalidate="novalidate">
{% csrf_token %}
{{ obj.as_p }}
<input type="submit" value="提交">
</form>
</body>

  从上面的小例子能看出,models的字段和forms的字段大部分都是重复的,所以,django给我们提供了一种更为简洁的ModelFrom

ModelForm的用法

forms.py

class UserInfoModelForm(forms.ModelForm):

    class Meta:
model = models.UserInfo # 与models建立了依赖关系
fields = "__all__"

views.py

def index(request):
if request.method == "GET":
obj = UserInfoModelForm()
return render(request,"index.html",{'obj':obj})
elif request.method == "POST":
obj = UserInfoModelForm(request.POST)
print(obj.is_valid()) # 这是方法,别忘记了加括号
print(obj.cleaned_data)
print(obj.errors)
return render(request,"index.html",{'obj':obj})

index.html

<body>
<form action="/index/" method="POST" novalidate="novalidate">
{% csrf_token %}
{{ obj.as_p }}
<input type="submit" value="提交">
</form>
</body>

ModelForm常见参数

自定义字段名(html显示的字段)

如何定义http上定义的字段呢,自定义写成中文的?之前的用法是在Form里写上label。Model Form定义要用verbose_name

指定显示那些字段

class UserInfo(models.Model):
username = models.CharField(max_length=32, verbose_name='用户')
email = models.EmailField(verbose_name='邮箱')
user_type = models.ForeignKey(to='UserType',to_field='id', verbose_name='类型')

如果不在model里定义,在modelForm里实现,利用labels

class UserInfoModelForm(forms.ModelForm):

    class Meta:
model = models.UserInfo
fields = "__all__"
labels = {
'username':'用户名',
'email':'邮箱',
}

指定需要展示的字段

fields = "__all__"上面展示所有的,也可以展示指定的列

 fields = ['username','email']   # 显示指定列
exclude = ['username'] # 排除指定列

错误信息

 error_messages = {
'__all__':{ # 整体错误信息 },
'email': {
'required': '邮箱不能为空',
'invalid': '邮箱格式错误..',
}
}

给字段添加css属性

widgets = {
'username': Fwidgets.Textarea(attrs={'class': 'c1'})
}

ModelForm的验证

跟form一样,ModleForm里面也有is_validcleaned_dataerrors

# Form验证:
UserInfoForm -> Form -> BaseForm( 包含is_valid等方法) # ModelForm验证:
UserInfoModelForm -> ModelForm -> BaseModelForm -> BaseForm

ModelForm对数据库操作

添加数据

如果数据验证通过,直接调用save()方法,django会自动往数据库里添加一条数据(会根据modles里的字段一一对应)

if obj.is_valid():
obj.save() # 创建数据

如果在如下一对多、多对多关系中,如:

class UserType(models.Model):
caption = models.CharField(max_length=32) class UserGroup(models.Model):
name = models.CharField(max_length=32) class UserInfo(models.Model):
username = models.CharField(max_length=32)
email = models.EmailField()
user_type = models.ForeignKey(to='UserType',to_field='id')
u2g = models.ManyToManyField(UserGroup)

这样的话,执行上面的obj.save()会自动在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() # 等价以下三句
# instance = obj.save(False)
# instance.save()
# obj.save_m2m()
return render(request,'index.html',{'obj': obj})

修改数据

修改表数据是,记得把instance信息也传进去,如:mf = UserInfoModelForm(request.POST,instance=user_obj)

不然是新建数据,而不是对某行数据进行修改。

编辑用户信息,新url方式保留默认数据

urls.py

url(r'^user_list/', views.user_list),
url(r'^edit-(\d+)/', views.user_edit),

views.py

def user_list(request):
li = models.UserInfo.objects.all().select_related('user_type') # 这里只能是外键,多对多字段也不可以
return render(request,'user_list.html',{'li': li}) def user_edit(request, nid):
# 获取当前id对象的用户信息
# 显示用户已经存在数据
if request.method == "GET":
user_obj = models.UserInfo.objects.filter(id=nid).first()
mf = UserInfoModelForm(instance=user_obj) # 把默认数据传递进去
return render(request,'user_edit.html',{'mf': mf, 'nid': nid})
elif request.method == 'POST':
# 数据修改的信息,给数据库的哪一行做修改?
user_obj = models.UserInfo.objects.filter(id=nid).first()
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})

user_list.html

<body>
<ul>
{% for row in li %}
<li>{{ row.username }} - {{ row.user_type.caption }} - <a href="/edit-{{ row.id }}/">编辑</a></li>
{% endfor %}
</ul>
</body>

user_edit.html

<body>
<form method="POST" action="/edit-{{ nid }}/">
{% csrf_token %}
{{ mf.as_p }}
<input type="submit" value="提交" />
</form>
</body>

  

 
 
 

最新文章

  1. Pointers and Dynamic Allocation of Memory
  2. SQL Server2000导出数据时包含主键、字段默认值、描述等信息
  3. mysql SQL SERVER 的算法
  4. 一个关于正整数x的约数个数的结论
  5. iOS 9之3D Touch
  6. webapi mvc路由注册
  7. Proxy 那点事儿
  8. python day07
  9. 逆向工程-真码保存在系统文件破解QQ游戏对对碰助手
  10. 20155208徐子涵《网络对抗》Exp2 后门原理与实践
  11. 洛谷P2657 windy数 [SCOI2009] 数位dp
  12. python学习——sys.argv
  13. bzoj 3122 : [Sdoi2013]随机数生成器 BSGS
  14. UOJ #131 【NOI2015】 品酒大会
  15. CSU 1351 Tree Counting
  16. JAVA学习目录
  17. [Unity&#160;Shader笔记]渲染路径--Forward渲染路径
  18. 一:Nginx知识整理
  19. static修饰java内部运行顺序
  20. myeclipse 下载 checkstyle 引入后不显示问题

热门文章

  1. 在 Laravel 中使用 MongoDB
  2. vulstudy
  3. JPG文件结构分析
  4. thinkPHP5 命名空间别名
  5. OLTP和 OLAP区别
  6. Connect4 Game
  7. oracle中表记录被另一个用户锁住
  8. java中讲讲PrintWriter的用法,举例?
  9. Java虚拟机内存管理小结
  10. 剑指offer42:数组和一个数字S,输出两个数的乘积最小的