zoukankan      html  css  js  c++  java
  • [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。


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

  • 相关阅读:
    移动 Web 开发技巧
    判断手机是苹果还是安卓,并且判断安卓的高低版本
    JavaScript判断移动端及pc端访问不同的网站
    input实时监控和获取焦点的问题,oninput,ononfocus
    几个CSS3动画
    canvas加载进度条
    animation动画兼容所有手机
    背景渐变,兼容所有手机端
    文字动画和文字镂空
    前端面试题
  • 原文地址:https://www.cnblogs.com/AngryZe/p/9667745.html
Copyright © 2011-2022 走看看