Django学习笔记之——Forms

前面学习的都只是如何显示数据,但一直没有关于如何响应用户提交的数据。
表单,是在web中,用户与服务器交互的重要途径。

import django.forms
form django import forms
之间的区别是什么?

form在Django中扮演的角色有:
*显示form
*验证用户提交的数据

form的定义
~~~~~~~~~~

form的定义与model的定义非常相似:
____________________________________________
from django import forms
class BookForm(forms.Form):
    isbn= forms.CharField(max_length=200)
    title = forms.CharField(max_length=200)
--------------------------------------------
定义了一个BookForm表单,表单里有isbn与title两项。

BookForm可以生成html表单文本,如下:
____________________________
book_form = BookForm()
html = book_form.as_table()
print(html)
----------------------------
执行打印出的结果是:
<tr><th><label for="id_isbn">Isbn:</label></th><td><input id="id_isbn" maxlength="50" name="isbn" type="text" /></td></tr>
<tr><th><label for="id_title">Title:</label></th><td><input id="id_title" maxlength="200" name="title" type="text" /></td></tr>

可以看出,打印出来的文本没有包含<form>与<input type="submit">,这些需要我们
在模板中指定。Form只负责isbn与title的输入,而不关心form的动作与提交方式。
所以,我们最好用模板的方法先定义好一个模板,如book-form.html:
_______________________________
<form action="." method="get">
    {{book_form}}
    <br>
    <input type="submit">
</form>
-------------------------------
在views.py中用render_to_response()生成HttpResponse:
____________________________________________________
def book_view(request):
    book_form = BookForm()
    response = render_to_response(‘book-form.html‘,
            {‘book_form‘:book_form.as_table()})
----------------------------------------------------
返回的页面源码:
<form action="." method="get">
    <tr><th><label for="id_isbn">Isbn:</label></th><td><input id="id_isbn" maxlength="50" name="isbn" type="text" /></td></tr>
<tr><th><label for="id_title">Title:</label></th><td><input id="id_title" maxlength="200" name="title" type="text" /></td></tr>
    <br>
    <input type="submit">
</form>

Form除了as_table()方法,还有as_ul()与as_p()方法,默认是as_table()方法。

Form是在 django/forms/forms.py 定义的。
打开forms.py文件,可以了解到,Form继承于BaseForm。
BaseForm的定义大致如下:
___________________________________________________________________________
class BaseForm(object):
    def __init__(self, data=None, files=None, auto_id=‘id_%s‘, prefix=None,
            initial=None, label_suffix=None):
        ...
    def as_table(self):
        ...
    def as_ul(self):
        ...
    def as_p(self):
        ...
    def __str__(self):
        return self.as_table()

class Form(BaseForm):
    ...
---------------------------------------------------------------------------
auto_id为<input id="id_xxx">,控件的自动id格式。为‘‘或None表示不需要id。
label_suffix为lable名称的后缀,默认为":",可以改。比如:label_suffix="="
prefix为name的前缀,如果设置了prefix="aaa",那么<input name="aaa-xxx">
initial为初始值字典。

上面BookForm中只用到了一种域:CharField。除此之外还有很多种。
Fields定义在django/forms/fields.py文件里。

打开fields.py文件,可以看到除CharField外还有更多的Field供选择:
Field
|--CharField
|  |--RegexField
|  |--EmailField
|  |--URLField
|  |--IPAddressField
|  |--GenericIPAddressField
|  `--SlugField
|--IntegerField
|  |--FloatField
|  `--DecimalField
|--BaseTomporalField
|  |--DateField
|  |--TimeField
|  `--DateTimeField
|--FileField        #file选择文件
|  `--ImageField
|--BooleanField     #checkbox
|  `--NullBooleanField  #select:Unknow,Yes,No
|--ChoiceField      #select
|  |--TypedChoiceField
|  |--FilePathField
|  `--MultipleChoiceField
|     `--TypedMultipleChoiceField
|--ComboField
`--MultiValueField
   `--SplitDateTimeField

每种Field有个默认的Widget。
__________________________________
class Field(object):
    widget = TextInput
    ...
class EmailField(CharField):
    widget = EmailInput
    ...
class FileField(Field):
    widget = ClearableFileInput
    ...
----------------------------------
Widget告诉Field生成哪种web控件。

我们也可以为Field指定Widget。
比如登陆表单:
_____________________________________________________________
class LoginForm(forms.Form):
    #email = forms.EmailField()
    email = forms.CharField(widget=widgets.EmailInput())
    password = forms.CharField(widget=widgets.PasswordInput())
-------------------------------------------------------------
password这个域不能用明文显示,所以更改了widget。

所有的Widget都定义在django/forms/widgets.py中。
有如下控件:
‘Media‘, ‘MediaDefiningClass‘, ‘Widget‘, ‘TextInput‘,
‘EmailInput‘, ‘URLInput‘, ‘NumberInput‘, ‘PasswordInput‘,
‘HiddenInput‘, ‘MultipleHiddenInput‘, ‘ClearableFileInput‘,
‘FileInput‘, ‘DateInput‘, ‘DateTimeInput‘, ‘TimeInput‘, ‘Textarea‘,
‘CheckboxInput‘, ‘SplitDateTimeWidget‘,
‘Select‘, ‘NullBooleanSelect‘, ‘SelectMultiple‘, ‘RadioSelect‘,
‘CheckboxSelectMultiple‘, ‘MultiWidget‘,

基于模型的表单
~~~~~~~~~~~~~~
根据模型的定义来自动定义表单。如下:
______________________________________
from django import forms
from models import Book
class BookModelForm(froms.ModelForm):
    class Meta:
        model = Book
--------------------------------------
而Book的定义在models.py里:
____________________________________________
class Book(models.Model):
    isbn = models.CharField(max_length=50)
    title = models.CharField(max_length=200)
    author = models.ForeignKey(‘Author‘)

def __unicode__(self):
        return self.title
--------------------------------------------
这样以来,BookModelForm也有了与Book对应的isbn,title,author。

保存ModelForm
~~~~~~~~~~~~~
ModelForm与一般的Form的重要区别是,ModelForm具有save()功能。能将表单里的数据
加入到数据库,并返回一个Model对象。
为了演示方便,我就不采用模板了。同样是引用上面BookModelForm与Book:
_________________________________________________________________
def add_book_view(request):
    book_form = forms.BookModelForm(request.GET)
    try:
        book_model = book_form.save()
        content = ‘<p>Add ‘ + book_model.title + ‘ success!</p>‘
    except:
        content =  ‘<form action="." method="get">‘
        content += book_form.as_p()
        content += ‘<input type="submit"></form>‘
    return HttpResponse(content)
-----------------------------------------------------------------
并将add_book_view视图的url指定为r‘^add-book/‘。

第一次访问/add-book/时,由于GET中没有参数,所以在book_form.save()就会抛出异
常。在except中返回个表单给用户。用户填好后提交。这次再处理时,GET里就有数据
了,所以book_form.save()正常,最后输出success消息。

有时,我们在save()时仅仅是想验证一下用户的输入,并不打算提交到数据为。
这里,只要save(commit=False)即可。
如此,在save(commit=False)时返回了book模型的对象。我们可以继而对其进一步修改
,再保存到数据库。
_____________________________________________________
        #book_model = book_form.save()
        book_model = book_form.save(commit=False)
        book_model.title = ‘Balabala‘
        book_model.save()
-----------------------------------------------------
第一行只是验证一下用户的输出是不是符合要求。然后对模型对象进行修改,最后才保
存到数据库去。就这样,在中间改了title,然后再保存到了数据库。

ModelForm显示个别域
~~~~~~~~~~~~~~~~~~~
ModelForm默认情况下,与Model是一致的。但是很多时候,并不是模型中所有的域都要
让用户填的。我们可以选择性地选择或排除个别域。
这里就要用到Meta的exclude或fields。exclude表示排除什么域,而fields表示需要显
示哪些域。二者不能同时使用。
_________________________________________________
class BookModelForm(forms.ModelForm):
    class Meta:
        model = Book
        exclude = (‘author‘) #表示不显示author域
-------------------------------------------------
_________________________________________________
class BookModelForm(forms.ModelForm):
    class Meta:
        model = Book
        fields = (‘title‘, ‘isbn‘)
        #表示只显示title与isbn域
-------------------------------------------------

重写ModelForm中的域
~~~~~~~~~~~~~~~~~~~
_________________________________________
class BookModelForm(forms.ModelForm):
    isbn = forms.CharField(max_length=13)
    class Meta:
        model = Book
-----------------------------------------
将Book中指定的CharField(max_length=50),改成了13。

新增ModelForm中的域
~~~~~~~~~~~~~~~~~~~
______________________________________
class BookModelForm(forms.ModelForm):
    review = forms.CharField()
    class Meta:
        model = Book
--------------------------------------
这样以来,BookModelForm不仅只有Book中的域,还有review。

表单的验证
~~~~~~~~~~
Form的is_valid()文件可以用来验证数据是否合法。
如果数据合法,Form对象则会有cleaned_data属性。如果不合法,则是errors。
__________________________________________________________________
def add_author_view(request):
    content = None
    if request.GET: # 检查GET是否有表单数据
        author_form = forms.AuthorModelForm(request.GET)
        if author_form.is_valid():  # 检查数据是否合法
            print(author_form.cleaned_data)
            try:
                author_form.save()
                content = ‘<p>Success</p>‘
            except:
                content = ‘<p>Something wrong while saving.</p>‘
        else:
            content = str(author_form.errors) # 用errors返回错误信息
    else:
        content =  ‘<form action=".">‘
        content += forms.AuthorModelForm().as_p()
        content += ‘<input type="submit"></form>‘
    return HttpResponse(content)
------------------------------------------------------------------
上面用到了author_form.is_valid()进行数据合法性验证。
如果成功,则会有author_form.cleaned_data,如果失败会有author_form.errors。
这两则只会存在一个,不会同时存在。

时间: 2024-11-05 05:54:05

Django学习笔记之——Forms的相关文章

Django学习笔记汇总

1. 学习历程 从学了Python以来,我都一直想着用它来做点什么.从开始用python来写简单的工具脚本,然后再是网络信息抓取程序. 听说可以用Python来做网站,所以我了解了一下web.py与Django.第一次接触Django,由于没有网络方面的基础,所以没弄两下就放弃了. 后来,我研究了一下Python自来的SimpleHTTPServer,然后读懂了CGIHTTPServer,才对Web的实质有了了解. 在这个基础上,我再次重拾Django.这次,终于学会了. 原来它是那么的美妙!

Django学习笔记(五)—— 表单

疯狂的暑假学习之  Django学习笔记(五)-- 表单 参考:<The Django Book> 第7章 1. HttpRequest对象的信息 request.path                                 除域名以外的请求路径,斜杠开头                      "/hello/" request.get_host()                      主机名                              

Python框架之Django学习笔记(十七)

Django框架之表单(续二) PS:本博客欢迎转发,但请注明博客地址及作者~ 博客地址:http://www.cnblogs.com/voidy/ <.)#)))≦ 今天的这篇博客将是Django学习笔记博客的最后一篇,基本每周最少一篇的Django框架学习,坚持到今天也实属不易,当然了,这个框架的学习仅仅是Django框架的基础部分了,不过也够我们平时搭个简易的网站或者个人博客什么的.希望通过这一系列的博文,让大家也从中体会到Django框架的魅力所在,如果很不幸,你没有体会到,只能说明我水

Django学习笔记 官网教程纠正 代码

原文: Django学习笔记 官网教程纠正 代码 Django学习笔记 4.模板初学中,照书例django book 出现以下异常 raise ImportError("Settings cannot be imported, because environment variable %s is undefined." % ENVIRONMENT_VARIABLE) ImportError: Settings cannot be imported, because environmen

Django 学习笔记(七)数据库基本操作(增查改删)

一.前期准备工作,创建数据库以及数据表,详情点击<Django 学习笔记(六)MySQL配置> 1.创建一个项目 2.创建一个应用 3.更改settings.py 4.更改models.py 5.同步数据 二.安装IPython方便debug sudo apt-get install ipython3 安装成功后用python manage.py shell 会自动进入Ipython交互解释器中,没有安装Ipython只有前两行代码,只进入到Python shell 中. Python 3.5

Django学习笔记 Day One

Time:2016年01月01日21:38:55 Description: 从今天开始我开始写我的Django学习笔记,因为网络上太多太杂乱的文章,不成系统,还有就是太多的培训机构讲述的东西过于简单,没有深入讲解Django,算是自己的一个小笔记吧,主要参考的是Django1.8的官方文档,地址:www.djangoproject.com,一家之言,大神勿喷! Content: Day One. First exploration of django? 我们在Web开发过程中,常常会遇到编写重复

Django学习笔记(三)—— 模型 model

疯狂的暑假学习之 Django学习笔记(三)-- 模型 model 参考:<The Django Book> 第5章 1.setting.py 配置 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.', # 用什么数据库管理系统 'NAME': '', # 数据库名称,如果用sqlite,要写完整路径 'USER': '', # 如果用sqlite,这个不用写 'PASSWORD': '', # 如果用sqlite,这个不用写

django学习笔记

用的windows操作系统,真是蛋疼啊,等赚了钱,我真要买一台苹果或者换个12寸的小本,用ubuntu,所以一下命令都是windows的,真心蛋疼啊,为什么没有自动补完啊 首先,随便下个django. 然后,进入命令行,进入django的文件夹键入如下命令 django>python setup.py install 经过短时间的等待,安装完成. 然后随便建一个文件夹,比如myproject,命令行进入文件夹,然后输入如下命令,一个django项目就算建好了 myproject>django-

Django学习笔记(四)—— Admin

疯狂的暑假学习之  Django学习笔记(四)-- Admin 参考:<The Django Book> 第6章 Django 可以使用admin自动创建管理界面. 1. 配置 django-admin.py startproject 创建的项目,如果没有注解掉默认的配置,python manage.py syncdb 创建用户后,直接 http://xxxxxx/admin 输入密码即可进入. 如果修改了配置文件,保证将 django.contrib.admin 加入setting.py 中