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>