《老鸟python 系列》视频上线了,全网稀缺资源,涵盖python人工智能教程,爬虫教程,web教程,数据分析教程以及界面库和服务器教程,以及各个方向的主流实用项目,手把手带你从零开始进阶高手之路!点击 链接 查看详情

把模型加入后台管理

阅读:334630507    分享到

有一个关键步骤我们还没做。让我们将自己的模块加入管理工具中,这样我们就能够通过这个漂亮的界面添加、修改和删除数据库中的对象了。我们将继续第五章中的 book 例子。在其中,我们定义了三个模块:PublisherAuthorBook

模型加入admin管理的方法

首先确保 settings.py 文件里的 INSTALLED_APPS 字段内加上 books app,如下:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'books',
]

然后在 books 目录下(mysite/books ),找到 admin.py 文件(如果没有的话,自己创建一个) ,然后输入以下代码:

from django.contrib import admin
from mysite.books.models import Publisher, Author, Book

admin.site.register(Publisher)
admin.site.register(Author)
admin.site.register(Book)

这些代码通知管理工具为这些模块逐一提供界面。

完成后,打开页面 http://127.0.0.1:8000/admin/,你会看到一个 Books 区域,其中包含 Authors、Books 和 Publishers。(你可能需要先停止,然后再启动服务(runserver ),才能使其生效。)

现在你拥有一个功能完整的管理界面来管理这三个模块了。很简单吧!

花点时间添加和修改记录,以填充数据库。如果你跟着第五章的例子一起创建 Publisher 对象的话(并且没有删除),你会在列表中看到那些记录。

这里需要提到的一个特性是,管理工具处理外键和多对多关系(这两种关系可以在Book 模块中找到)的方法。 作为提醒,这里有个Book 模块的例子:

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

    def __unicode__(self):
        return self.title

在 Add book 页面中(http://127.0.0.1:8000/admin/books/book/add/),外键 publisher 用一个选择框显示,多对多 字段 author 用一个多选框显示。 点击两个字段后面的绿色加号,可以让你添加相关的记录。 举个例子,如果你点击 Publisher 后面的加号,你将会得到一个弹出窗口来添加一个 publisher。当你在那个窗口中成功创建了一个 publisher 后,Add book 表单会自动把它更新到字段上去。

Admin是如何工作的

在幕后,管理工具是如何工作的呢?其实很简单。

当服务启动时,Django 从url.py 引导 URLconf,然后执行 admin.autodiscover() 语句。这个函数遍历 INSTALLED_APPS 配置,并且寻找相关的 admin.py文件。如果在指定的 app 目录下找到 admin.py,它就执行其中的代码。

books 应用程序目录下的 admin.py 文件中,每次调用 admin.site.register() 都将那个模块注册到管理工具中。管理工具只为那些明确注册了的模块显示一个编辑/修改的界面。

应用程序 django.contrib.auth 包含自身的 admin.py ,所以 Users 和 Groups 能在管理工具中自动显示。其它的 django.contrib 应用程序,如 django.contrib.redirects,其它从网上下在的第三方 Django 应用程序一样,都会自行添加到管理工具。

综上所述,管理工具其实就是一个 Django 应用程序,包含自己的模块、模板、视图和 URLpatterns。你要像添加自己的视图一样,把它添加到 URLconf 里面。你可以在 Django 基本代码中的 django/contrib/admin 目录下,检查它的模板、视图和 URLpatterns,但你不要尝试直接修改其中的任何代码,因为里面有很多地方可以让你自定义管理工具的工作方式。(如果你确实想浏览 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

因此,这说起来有点复杂:如果你想允许一个日期型(DateFieldTimeFieldDateTimeField)或数字型(IntegerFieldDecimalFieldFloatField)字段为空,你需要使用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;

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


如果以上内容对您有帮助,请老板用微信扫一下赞赏码,赞赏后加微信号 birdpython 领取免费视频。


登录后评论