Python的Django框架中设置日期和字段可选的方法

设置字段可选

在摆弄了一会之后,你或许会发现管理工具有个限制:编辑表单需要你填写每一个字段,然而在有些情况下,你想要某些字段是可选的。 举个例子,我们想要Author模块中的email字段成为可选,即允许不填。 在现实世界中,你可能没有为每个作者登记邮箱地址。

为了指定email字段为可选,你只要编辑Book模块(回想第五章,它在mysite/books/models.py文件里),在email字段上加上blank=True。代码如下:

class Author(models.Model):
  first_name = models.CharField(max_length=30)
  last_name = models.CharField(max_length=40)
  email = models.EmailField(**blank=True** )

这些代码告诉Django,作者的邮箱地址允许输入一个空值。 所有字段都默认blank=False,这使得它们不允许输入空值。

这里会发生一些有趣的事情。 直到现在,除了__unicode__()方法,我们的模块充当数据库中表定义的角色,即本质上是用Python的语法来写CREATE TABLE语句。 在添加blank=True过程中,我们已经开始在简单的定义数据表上扩展我们的模块了。 现在,我们的模块类开始成为一个富含Author对象属性和行为的集合了。 email不但展现为一个数据库中的VARCHAR类型的字段,它还是页面中可选的字段,就像在管理工具中看到的那样。

当你添加blank=True以后,刷新页面Add author edit form (http://127.0.0.1:8000/admin/books/author/add/ ),将会发现Email的标签不再是粗体了。 这意味它不是一个必填字段。 现在你可以添加一个作者而不必输入邮箱地址,即使你为这个字段提交了一个空值,也再不会得到那刺眼的红色信息“This field is required”。
设置日期型和数字型字段可选

虽然blank=True同样适用于日期型和数字型字段,但是这里需要详细讲解一些背景知识。

SQL有指定空值的独特方式,它把空值叫做NULL。NULL可以表示为未知的、非法的、或其它程序指定的含义。

在SQL中, NULL的值不同于空字符串,就像Python中None不同于空字符串("")一样。这意味着某个字符型字段(如VARCHAR)的值不可能同时包含NULL和空字符串。

这会引起不必要的歧义或疑惑。 为什么这条记录有个NULL,而那条记录却有个空字符串? 它们之间有区别,还是数据输入不一致? 还有: 我怎样才能得到全部拥有空值的记录,应该按NULL和空字符串查找么?还是仅按字符串查找?

为了消除歧义,Django生成CREATE TABLE语句自动为每个字段显式加上NOT NULL。 这里有个生成Author模块的例子:

CREATE TABLE "books_author" (
  "id" serial NOT NULL PRIMARY KEY,
  "first_name" varchar(30) NOT NULL,
  "last_name" varchar(40) NOT NULL,
  "email" varchar(75) NOT NULL
)
;

在大多数情况下,这种默认的行为对你的应用程序来说是最佳的,因为它可以使你不再因数据一致性而头痛。 而且它可以和Django的其它部分工作得很好。如在管理工具中,如果你留空一个字符型字段,它会为此插入一个空字符串(而* 不是*NULL)。

但是,其它数据类型有例外:日期型、时间型和数字型字段不接受空字符串。 如果你尝试将一个空字符串插入日期型或整数型字段,你可能会得到数据库返回的错误,这取决于那个数据库的类型。 (PostgreSQL比较严禁,会抛出一个异常;MySQL可能会也可能不会接受,这取决于你使用的版本和运气了。)在这种情况下,NULL是唯一指定空值的方法。 在Django模块中,你可以通过添加null=True来指定一个字段允许为NULL。

因此,这说起来有点复杂: 如果你想允许一个日期型(DateField、TimeField、DateTimeField)或数字型(IntegerField、DecimalField、FloatField)字段为空,你需要使用null=True * 和* blank=True。

为了举例说明,让我们把Book模块修改成允许 publication_date为空。修改后的代码如下:

class Book(models.Model):
  title = models.CharField(max_length=100)
  authors = models.ManyToManyField(Author)
  publisher = models.ForeignKey(Publisher)
  publication_date = models.DateField(**blank=True, null=True** )

添加null=True比添加blank=True复杂。因为null=True改变了数据的语义,即改变了CREATE TABLE语句,把publication_date字段上的NOT NULL删除了。 要完成这些改动,我们还需要更新数据库。

出于某种原因,Django不会尝试自动更新数据库结构。所以你必须执行ALTER TABLE语句将模块的改动更新至数据库。 像先前那样,你可以使用manage.py dbshell进入数据库服务环境。 以下是在这个特殊情况下如何删除NOT NULL:

ALTER TABLE books_book ALTER COLUMN publication_date DROP NOT NULL;

(注意:以下SQL语法是PostgreSQL特有的。)

我们将在第十章详细讲述数据库结构更改。

现在让我们回到管理工具,添加book的编辑页面允许输入一个空的publication date。

(0)

相关推荐

  • 全面解读Python Web开发框架Django

    花了两周时间,利用工作间隙时间,开发了一个基于Django的项目任务管理Web应用.项目计划的实时动态,可以方便地被项目成员查看(^_^又重复发明轮子了).从前台到后台,好好折腾了一把,用到:HTML.CSS.JavaScript.Apache.Python.mod_wsgi.Django.好久不用CSS和JavaScript了,感到有点生疏了,查了无数次手册.后台Django开发环境的搭建也花了不少时间和精力.记录下来,免得以后走弯路.同时给大家推荐一下Django框架,如果你想非常快速地编写

  • Python的Django框架中的表单处理示例

    组建一个关于书籍.作者.出版社的例子: from django.db import models class Publisher(models.Model): name = models.CharField(max_length=30) address = models.CharField(max_length=50) city = models.CharField(max_length=60) state_province = models.CharField(max_length=30) c

  • 详解Python的Django框架中的templates设置

    TEMPLATES Django 1.8的新特性 一个列表,包含所有在Django中使用的模板引擎的设置.列表中的每一项都是一个字典,包含某个引擎的选项. 以下是一个简单的设定,告诉Django模板引擎从已安装的应用程序(installed applications)的templates子目录中读取模板: TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'APP_DIRS': True,

  • 使用Python的Django框架实现事务交易管理的教程

    如果你花费了很多的时间去进行Django数据库事务处理的话,你将会了解到这是让人晕头转向的. 在过去,只是提供了简单的基础文档,要想清楚知道它是怎么使用的,还必须要通过创建和执行Django的事务处理. 这里有众多的Django事务处理的名词,例如:commit_on_success , commit_manually , commit_unless_maneged,rollback_unless_managed,enter_transaction_management,leace_transa

  • 分析Python的Django框架的运行方式及处理流程

    之前在网上看过一些介绍Django处理请求的流程和Django源码结构的文章,觉得了解一下这些内容对开发Django项目还是很有帮助的.所以,我按照自己的逻辑总结了一下Django项目的运行方式和对Request的基本处理流程. 一.Django的运行方式 运行Django项目的方法很多,这里主要介绍一下常用的方法.一种是在开发和调试中经常用到runserver方法,使用Django自己的web server:另外一种就是使用fastcgi,uWSGIt等协议运行Django项目,这里以uWSG

  • 详解Python的Django框架中的通用视图

    通用视图 1. 前言 回想一下,在Django中view层起到的作用是相当于controller的角色,在view中实施的 动作,一般是取得请求参数,再从model中得到数据,再通过数据创建模板,返回相应 响应对象.但在一些比较通用的功能中,比如显示对象列表,显示某对象信息,如果反复 写这么多流程的代码,也是一件浪费时间的事,在这里,Django同样给我们提供了类似的 "shortcut"捷径--通用视图. 2. 使用通用视图 使用通用视图的方法就是在urls.py这个路径配置文件中进

  • python模拟Django框架实例

    一.python实现web服务器 web开发首先要有web服务器才行.比如apache,但是在开发阶段最好有一个简单方便的开发服务器, 容易重启进行调试,等开发调试完毕后,再将代码部署到成熟稳定高效的web服务器. # -*- coding: utf-8 -*- from wsgiref import simple_server # 定义一个输出 hello world 和环境变量的简单web应用程序 def hello_app(environ, start_response): # 输出 ht

  • 用Python的Django框架完成视频处理任务的教程

    Stickyworld 的网页应用已经支持视频拨放一段时间,但都是通过YouTube的嵌入模式实现.我们开始提供新的版本支持视频操作,可以让我们的用户不用受制于YouTube的服务. 我过去曾经参与过一个项目,客户需要视频转码功能,这实在不是个容易达成的需求.需要大量的读取每一个视频.音讯与视频容器的格式再输出符合网页使用与喜好的视频格式. 考虑到这一点,我们决定将转码的工作交给 Encoding.com .这个网站可以免费让你编码1GB大小的视频,超过1GB容量的文件将采取分级计价收费. 开发

  • python常用web框架简单性能测试结果分享(包含django、flask、bottle、tornado)

    测了一下django.flask.bottle.tornado 框架本身最简单的性能.对django的性能完全无语了. django.flask.bottle 均使用gunicorn+gevent启动,单进程,并且关闭DEBUG,请求均只返回一个字符串ok. tornado直接自己启动,其他内容一致. 测试软件为 siege,测试os为cenos6 64位,测试命令为: 复制代码 代码如下: siege -c 100 -r 100 -b http://127.0.0.1:5000/ django

  • 详解Python的Django框架中的Cookie相关处理

    浏览器的开发者在很早的时候就已经意识到, HTTP's 的无状态会对Web开发者带来很大的问题,于是(cookies)应运而生. cookies 是浏览器为 Web 服务器存储的一小段信息. 每次浏览器从某个服务器请求页面时,它向服务器回送之前收到的cookies 来看看它是怎么工作的. 当你打开浏览器并访问 google.com ,你的浏览器会给Google发送一个HTTP请求,起始部分就象这样: GET / HTTP/1.1 Host: google.com ... 当 Google响应时,

随机推荐