[Django学习]Django基础(14)_django-form

一 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。


 

  注明:学习资料来自“再敲一行代码的个人空间”以及“杨仕航的博客”

posted on 2018-11-26 20:04  AngryZe  阅读(191)  评论(0编辑  收藏  举报

导航