ModelForm
ModelForm结合了Form和Model,将models的field类型映射成forms的field类型,复用了Model和Model验证,
写更少的代码,并且还实现了存储数据库的简单方法
models field类型和forms field类型映射关系
https://docs.djangoproject.com/en/1.11/topics/forms/modelforms/#field-types
from django.db import models
from django.forms import ModelForm
from django import forms
from django.utils.translation import ugettext_lazy as _ TITLE_CHOICES = (
('MR', 'Mr.'),
('MRS', 'Mrs.'),
('MS', 'Ms.'),
) class Author(models.Model):
name = models.CharField(max_length=100)
title = models.CharField(max_length=3, choices=TITLE_CHOICES)
birth_date = models.DateField(blank=True, null=True) def __str__(self):
return self.name class Book(models.Model):
name = models.CharField(max_length=100)
authors = models.ManyToManyField('Author') def __str__(self):
return self.name class AuthorForm(ModelForm):
class Meta:
model = Author
fields = ['name', 'title', 'birth_date'] class BookForm(ModelForm):
class Meta:
model = Book
fields = ['name', 'authors']
ModelForm save()方法
form.is_valid()之后,form.save()可以直接保存到数据库
Django ModelForm Meta
用来配置前端模板的各种选项,可以和Form对应起来,labels、widgets、help_texts、error_messages等,复数形式
class AuthorForm(ModelForm):
class Meta:
model = Author
fields = ['name', 'title', 'birth_date']
# fields = '__all__'
# exclude = ('birth_date',)
labels = {
'name': 'Writer',
}
widgets = {
'name': forms.Textarea(attrs={'cols': 80, 'row':20})
}
help_texts = {
'name': _('Some useful help text') # 需要翻译文件
}
error_messages = {
'name':{
'max_length':_("This writer's name is too long.")
},
}
Django ModelForm 自定义验证
先进行 class Meta中的Model验证,在进行每个字段 clean_name()验证,最后进行clean()验证
class AuthorForm(ModelForm):
class Meta:
model = Author
fields = ['name', 'title', 'birth_date'] # 校验单个字段
def clean_name(self):
name = self.cleaned_data['name'] # 获取数据
if len(name) < 30:
raise ValidationError("Length must be more than 30") # 非法时,抛出异常
return name # 返回该字段值 # 多个字段联合校验
def clean(self):
clean_data = super(AuthorForm, self).clean()
name = clean_data.get('name')
title = clean_data.get('title')
if len(name) < 40 and title == "MR":
raise ValidationError('xxxx') # 对应 form.non_field_errors
view和模板中使用 Model Form(最佳实践)
# form.py
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField() def __str__(self):
return self.name class PublisherForm(ModelForm):
class Meta:
model = Publisher
# fields = ['name', 'address', 'city', 'state_province', 'country', 'website']
# fields = '__all__'
fields = "__all__" # veiws.py
def publisher_add2(request):
if request.method == "POST":
form = PublisherForm(request.POST)
if form.is_valid():
publisher = form.save()
return HttpResponse('添加成功')
else:
form = PublisherForm()
return render(request, 'books2/publisher_add.html', {'form': form }) # books/templates/publish_add.html
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit"/>
</form>
POST:
- form = PublisherForm(request.POST)
- form.is_valid()
- form.save()
GET:
- form = PublisherForm()
Django Model Form inital and instance
model中default='中国' 可以在数据库的层面设置默认值,前端是可以正常显示默认值的
form = PublisherForm(initial={'city':'北京'}),在view 层面设置默认值,字段层面
publisher = get_object_or_404(Publisher, id=publisher_id); form = PublisherForm(instance=publisher),默认值是整个对象
form = PublisherForm(request.POST, instance=publisher),更新数据时,request.POST满足条件时更新;不满足条件时还是原来publisher
# views.py
def publisher_update(request, publisher_id):
publisher = get_object_or_404(Publisher, pk=publisher_id) if request.method == "POST":
form = PublisherForm(request.POST, instance=publisher)
if form.is_valid():
publisher = form.save()
return HttpResponse('更新成功') form = PublisherForm(instance=publisher)
return render(request, 'books2/publisher_update.html', {'form':form})
Django form bootstrap 插件
参考链接:
https://github.com/dyve/django-bootstrap3
安装:
pip install -i https://pypi.doubanio.com/simple/ --trusted-host pypi.doubanio.com django-bootstrap3
使用:
{% load bootstrap3 %} <div class="container">
<form method="post">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button type="submit" class="btn btn-primary">{% bootstrap_icon "star" %} Submit</button>
{% endbuttons %}
</form>
</div>