一 Html-Form
<form action="/your-name/" method="post"> <label for="your_name">Your name: </label> <input id="your_name" type="text" name="your_name" value="{{ current_name }}"> <input type="submit" value="OK"> </form>
这是一个非常简单的html-form,它告诉浏览器使用GET方法创建一个表单,包括一个标签,一个文本框以及一个按钮;
当点击按钮时,使用POST方法将表单的数据提交给URL 为“/you-name/”对应的方法。
而实际应用中,表单可能包含数十个或数百个字段。
其中,有些字段需要预先填充;
或者开发者希望用户在结束操作之前多次完成编辑 - 提交周期;
有些字段需要在提交表单前在浏览器中进行一些验证;
希望使用更复杂的字段,允许用户执行诸如从日历中选择日期等操作。
以上的这些操作使用Html-Form来进行开发设计,工作量很大,程序结构也比较复杂。
二 Django-Form
(一)认识Django-Form
from django import forms class YourNameForm(forms.Form): your_name = forms.CharField(label='Your name: ', widget=forms.TextInput(attrs={'class':'formcontrol','placeholder':'Your name'}))
以上是在django项目框架下的某个app中创建的forms.py文件。
django提供form库把框架里三个主要的组建连结在了一起:
-
- 模型里定义的数据字段
- 模版里显示的html表单标签
- 检验用户输入和显示错误信息
(二) Django-Form的优点
-
- 对用户提交的数据验证
- 自动生成错误信息
- 打包用户提交的正确信息
- 能够在input框里保留上次输入的错误信息
- 定制页面的html标签
(三)定义表单
1. 常规定义
表单,和模型一样,其实就是变量对象的集合。表单代表特定web页面内变量的表单,模型代表数据表中的字段。
from django import forms class YourNameForm(forms.Form): your_name = forms.CharField(label='Your name: ', widget=forms.TextInput(attrs={'class':'formcontrol','placeholder':'Your name'}))
2. ModelForm定义
为了保持DRY原则,Django允许使用一种特殊的Form变型ModelForm来为任何模型类或实例取得一个Form子类。
但是,ModelForm必须包含一个Meta嵌套类,Meta嵌套类有一个必需的model属性,它的值就是所需的Model类。
from django import forms from myproject.myapp.models import Person class PersonForm(forms.ModelForm): class Meta: model=Person
一般而言,你要为你创建的每一个Model类至少定义一个ModelForm类。这种方法突出了数据定义与数据输入和数据验证的分离,提供强大的灵活性。
(三)渲染表单
1. 在app目录下新建forms.py文件,定义所需的form
from django import forms from django.contrib.contenttypes.models import ContentType from django.db.models import ObjectDoesNotExist from ckeditor.widgets import CKEditorWidget class CommentForm(forms.Form): content_type = forms.CharField(widget=forms.HiddenInput) object_id = forms.IntegerField(widget=forms.HiddenInput) comment_text = forms.CharField(widget=CKEditorWidget(config_name='comment_ckeditor')) def __init__(self, *args, **kwargs): if 'user' in kwargs: self.user = kwargs.pop('user') super(CommentForm,self).__init__(*args, **kwargs) def clean(self): #验证用户是否登录 if self.user.is_authenticated: self.cleaned_data['user'] = self.user else: raise forms.ValidationError('用户尚未登录') # 验证评论对象是否存在 content_type = self.cleaned_data['content_type'] object_id = self.cleaned_data['object_id'] try: model_class = ContentType.objects.get(model=content_type).model_class() model_obj = model_class.objects.get(pk=object_id) self.cleaned_data['content_object'] = model_obj except ObjectDoesNotExist: raise forms.ValidationError('评论对象不存在')
2. 在app.views.py中实例化表单
def blog_detail(request, blog_pk): """ render data to blog_detail.html """ blog = get_object_or_404(Blog, pk=blog_pk) read_cookie_key = read_statistics_once_read(request, blog) blog_content_type = ContentType.objects.get_for_model(blog) comments = Comment.objects.filter(content_type=blog_content_type,object_id=blog.pk) context = {} context['blog'] = blog context['previous_blog'] = Blog.objects.filter(create_time__gt=blog.create_time).last() context['next_blog'] = Blog.objects.filter(create_time__lt=blog.create_time).first() context['comments'] = comments //实例化表单 context['comment_form'] = CommentForm(initial={'content_type':blog_content_type.model,'object_id':blog_pk}) response = render(request,'blog/blog_detail.html', context) response.set_cookie(read_cookie_key,'true') return response
3. 在template.html中的<form>标签内引用实例化的表单
<form action="{% url 'update_comment' %}" method="POST" sytle="overflow:hidden">
{% csrf_token %}
<label>{{ user.username }},欢迎评论</label>
{% for field in comment_form %}
{{ field }}
{% endfor %}
<input type="submit" value="评论" class="btn btn-primary" style="float:right">
</form>
(四)验证和清理
要让表单运行它的验证程序,可以显式调用is_valid方法。常规的方式是:
def update_comment(request): referer = request.META.get('HTTP_REFERER',reverse('home')) #获取POST数据 comment_form = CommentForm(request.POST, user=request.user) #调用is_valid方法验证数据 if comment_form.is_valid(): comment = Comment() #验证通过,使用其cleaned_data数据 comment.user = comment_form.cleaned_data['user'] comment.comment_text = comment_form.cleaned_data['comment_text'] comment.content_object = comment_form.cleaned_data['content_object'] comment.save() return redirect(referer) else: #验证失败,使用其errors数据 return render(request, 'error.html', {'message':comment_form.errors,'redirect_to':referer})
当执行验证时,表单对象对得到两个新属性之一:一个是包含错误信息的字典errors,或是一个包含原本绑定到表单上的值的“干净”版的字典cleaned_data。
注明:学习资料来自“再敲一行代码的个人空间”以及“杨仕航的博客”