forms表单与modelfrom使用
详细参考链接:点击
数据结构models.py
from django.db import models
# Create your models here.
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8, decimal_places=2)
date = models.DateField(null=True)
publish = models.ForeignKey(to=‘Publish‘, on_delete=models.CASCADE)
authors = models.ManyToManyField(‘Author‘)
def __str__(self):
return self.title
class Meta:
verbose_name = ‘书籍表‘
class Publish(models.Model):
title = models.CharField(max_length=24)
site = models.CharField(max_length=80)
# author = models.
def __str__(self):
return self.title
class Meta:
verbose_name = ‘出版社‘
class Author(models.Model):
name = models.CharField(max_length=10)
def __str__(self):
return self.name
class Meta:
verbose_name = ‘作者‘model.py
在页面上对数据进行操作时,如果不用forms组件,在设计HTML页面时,会有冗长的代码,特别是修改数据页面,视图中处理数据也同样不方便:
<form action="" method="post" novalidate>
<div>书名:
<input type="text" value="{{ old_book.title }}">
</div>
<div>价格:
<input type="text" value="{{ old_book.price }}">
</div>
<div>时间:
<input type="date" value="{{ old_book.date }}">
</div>
<div>出版社:
<select name="publish" id="">
{% for punlish in all_publishs %}
{% if old_book.publish == punlish %}
<option value="{{ punlish.id }}" selected>{{ punlish.title }}</option>
{% else %}
<option value="{{ punlish.id }}">{{ punlish.title }}</option>
{% endif %}
{% endfor %}
</select>
</div>
<div>作者:
<select name="author" id="" multiple>
{% for author in all_authors %}
{% if author in old_book.authors.all %}
<option value="{{ author.id }}" selected>{{ author.name }}</option>
{% else %}
<option value="{{ author.id }}">{{ author.name }}</option>
{% endif %}
{% endfor %}
</select>
<input type="submit">
</form>
</div>HTML页面冗长的代码
def edit_book(request):
book_forms = forms.AddBook()
id = request.GET.get(‘id‘)
old_book = models.Book.objects.filter(id=id).first()
all_publishs = models.Publish.objects.all()
all_authors = models.Author.objects.all()
if request.method == ‘POST‘:
submit = forms.AddBook(request.POST)
if submit.is_valid():
return HttpResponse(‘ok‘)
return render(request, ‘editbook.html‘,
{‘book_forms‘: book_forms, ‘old_book‘: old_book, ‘all_publishs‘: all_publishs,
‘all_authors‘: all_authors})视图函数中冗长的代码
用上modelform组件后:
{% for fields in book_forms %}
<div>
{{ fields.label }}
{{ fields }} <span style="color: red">{{ fields.errors.0 }}</span>
</div>
{% endfor %}def edit_book(request):
id = request.GET.get(‘id‘)
old_book = models.Book.objects.filter(id=id).first()
book_forms = forms.ModelFromBook(instance=old_book) # modelform接收一个参数instance,为model对象,它自动将这个model对象的值填充到form表单
if request.method == "POST":
book_forms = forms.ModelFromBook(request.POST, instance=old_book)
if book_forms.is_valid():
book_forms.save() # 将修改后的值,直接更新
return redirect(‘/index/‘)
else:
return render(request, ‘editbook.html‘, {‘book_forms‘: book_forms,})
return render(request, ‘editbook.html‘, locals())使用forms组件时需要注意的地方:
from django import forms
from django.forms import widgets
from app01 import models
class AddBook(forms.Form):
title = forms.CharField(max_length=20, min_length=5,
error_messages={‘required‘: ‘标题不能为空‘,
‘min_length‘: ‘标题最少为5个字符‘,
‘max_length‘: ‘标题最多为20个字符‘},
)
price = forms.DecimalField(max_digits=8, decimal_places=2)
date = forms.DateField(
widget=widgets.TextInput(attrs={‘type‘: ‘date‘})
)
publish = forms.ModelChoiceField(queryset=models.Publish.objects.all()) # 单选select框 queryset可以从models表中取queryset对象
authors = forms.ModelMultipleChoiceField(queryset=models.Author.objects.all()) # 多选select框forms
def add_book(request):
book_forms = forms.AddBook()
if request.method == ‘POST‘:
book_forms = forms.AddBook(request.POST)
if book_forms.is_valid():
title = request.POST.get(‘title‘)
price = request.POST.get(‘price‘)
date = request.POST.get(‘date‘)
publish = request.POST.get(‘publish‘)
authors = request.POST.getlist(‘authors‘)
book_obj = models.Book.objects.create(title=title, price=price, date=date, publish_id=publish)
book_obj.authors.add(*authors)
return redirect(‘/index/‘)
else:
print(book_forms.errors)
return render(request,‘addbook.html‘,{"book_forms": book_forms})
return render(request, ‘addbook.html‘, {‘book_forms‘: book_forms})views
<div>
<form action="" method="post" novalidate>
{% csrf_token %}
{% for book_form in book_forms %}
<p>
{{ book_form.label }}
{{ book_form }} <span>{{ book_form.errors.0 }}</span>
</p>
{% endfor %}
<input type="submit">
</form>
</div>HTML
1、使用单选与多选框时,queryset参数接收一个queryset对象,可以从models取到。error_messages参数自定义错误提示信息,widgets可以指定input框,并设置样式
2、提交数据后,视图接收数据,把数据传给forms对象,is_valid方法对数据进行校验,没有错误返回True,之后可以进行数据表操作。有错误返回Flase,errors方法返回所有对应的错误信息的html标签,在模板语言中可以直接通过字段调用错误信息进行渲染,注意需要使用下标获取第一个错误信息
3、forms的校验方式简洁,但是在校验成功后的数据添加或者更新操作依然麻烦,需要手动的获取每一条数据后,再添加到数据库。modelform很好的解决了这个问题。
modelform使用:
from django import forms
from django.forms import widgets
from app01 import models
class ModelFromBook(forms.ModelForm):
class Meta:
model = models.Book
fields = ‘__all__‘ # [‘title‘,‘price‘]
widgets = {‘date‘: forms.widgets.TextInput(attrs={‘type‘: ‘date‘,}),
# ‘title‘: forms.widgets.TextInput(attrs={‘class‘: ‘form-control‘}),
# ‘price‘: forms.widgets.TextInput(attrs={‘class‘: ‘form-control‘}),
# ‘publish‘: forms.widgets.TextInput(attrs={‘class‘: ‘form-control‘}),
# ‘authors‘: forms.widgets.TextInput(attrs={‘class‘: ‘form-control‘}),
}
labels = {‘title‘: ‘书名‘,‘date‘: ‘时间‘,‘price‘: ‘价格‘,‘publish‘: ‘出版社‘,‘authors‘:‘作者‘}
error_messages = {‘title‘:{‘required‘: ‘书名不能为空‘},
}modelform
# 通过modelform添加数据
def add_book(request):
book_forms = forms.ModelFromBook()
if request.method == ‘POST‘:
book_forms = forms.ModelFromBook(request.POST)
if book_forms.is_valid():
book_forms.save() # save即可自己添加所有数据
return redirect(‘/index/‘)
else:
return render(request,‘addbook.html‘,{‘book_forms‘:book_forms})
return render(request, ‘addbook.html‘, {‘book_forms‘: book_forms})views
<div>
<form action="" method="post" novalidate>
{% csrf_token %}
{% for book_form in book_forms %}
<p>
{{ book_form.label }}
{{ book_form }} <span>{{ book_form.errors.0 }}</span>
</p>
{% endfor %}
<input type="submit">
</form>
</div>HTML
1、modelform接收一个参数instance,为model对象,它自动将这个model对象的每个字段值填充到form表单,前端页面的输入框自动将原来的数据填充
2、更新数据时,同样只需要传入instance参数,校验通过后,只需调用save方法即可将原来的数据更新。
3、其余方法与forms基本一致,只是在创建forms类不同