django学习笔记---第六章:Admin

本文介绍了在Django中如何自定义Admin设置,包括日期和数字字段的可选性、自定义字段标签、ModelAdmin类的定制以及列表显示的调整。通过设置`null=True`和`blank=True`允许字段为空,使用`verbose_name`定义字段标签,以及通过ModelAdmin类控制管理界面的显示字段和排序方式。
摘要由CSDN通过智能技术生成

django是一个开源web框架,学习起来里面细节很多。

因为我现在看的项目catmaid 5d就是基于django这个框架开发的。现在catmaid 5d资料不全,而且代码有各种bug。就需要回过头从catmaid 5d源码入手。在调试的过程中,经常会进入到django的源码里。所有就很有必要学习django的很多特性。熟练运用django,理解django工作的流程。

我这里用的数据库是PostgreSQL 9.5

设置日期型和数字型字段可选

django模型代码,对应为SQL里的CREATE TABLE语句
但现在,我们的模块类开始成为一个富含Author对象属性和行为的集合了。

class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField(blank=True, verbose_name='e-mail') #blank=True allows email to be null

    # Add the string representation of the model
    def __unicode__(self):
        return u'%s %s' % (self.first_name, self.last_name)

上述python代码对应的SQL语句为:

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生成CREATE TABLE语句自动为每个字段显式加上NOT NULL。

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

重点来了:

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

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

接下来看代码就会明白了:
python模型

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

    # Add the string representation of the module
    def __unicode__(self):
        return self.title

注意上面的:
publication_date = models.DateField(blank=True)
这是一个日期型属性,也同时表示Book数据表的一个列

下面是对应PostgreSQL的SQL代码:
在django中,用命令

python manage.py sqlall books

其中books是app的名称
这个命令就可以输出books这个app里所有模型的SQL语句

对应的SQL语句:

CREATE TABLE "books_book" (
    "id" serial NOT NULL PRIMARY KEY,
    "title" varchar(100) NOT NULL,
    "publisher_id" integer NOT NULL REFERENCES "books_publisher" ("id") DEFERRABLE INITIALLY DEFERRED,
    "publication_date" date NOT NULL
)
;

注意这句:
“publication_date” date NOT NULL

也就是默认创建的CREATE TABLE里的列都是NOT NULL

即使是:
publication_date = models.DateField(blank=True)
这样加了blank=True

再看对比:
python模型代码:


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)

    # Add the string representation of the module
    def __unicode__(self):
        return self.title

对应的SQL语句:

CREATE TABLE "books_book" (
    "id" serial NOT NULL PRIMARY KEY,
    "title" varchar(100) NOT NULL,
    "publisher_id" integer NOT NULL REFERENCES "books_publisher" ("id") DEFERRABLE INITIALLY DEFERRED,
    "publication_date" date
)
;

这时注意:
“publication_date” date
没有NOT NULL这个约束了

因此,结论就是:
就是在python代码加上
publication_date = models.DateField(blank=True, null=True)

null=True
就是在创建SQL语句时,去掉NOT NULL这个约束

blank=True是在admin中,手动给一个表添加一条记录时,如果有一个属性是blank=True,那么当不填该属性时,django会自动给这个列填上空字符串

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

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

ALTER TABLE books_book ALTER COLUMN publication_date DROP NOT NULL;

(注意:上面SQL语法是PostgreSQL特有的。)

自定义字段标签

首先说一下,什么是字段标签。初看名字不知道具体指代什么含义。坑爹呀
看个图吧:
这里写图片描述

在上图中,Change author中的author就是数据表名称。这些就明白了,这是数据表author中的一条记录。
红框圈中的就是author数据表的一个列了。
First name对应列名称。

这里的First name, Last name, E-mail就表示字段标签
所以,字段标签就是对应数据库表里的列。
自定义就是说可以自己对字段标签重新个起名字而已。

首先说一下,django默认生成字段标签的规则:

在编辑页面中,每个字段的标签都是从模块的字段名称生成的。 规则很简单:
用空格替换下划线;首字母大写。例如:Book模块中publication_date的标签是Publication date。

So,既然已经有了默认的生成标签的规则,为什么还要自定义呢??
我猜,可能是应为有时候用默认的规则生成的标签太丑了→_→

下面是文档里的原话:

然而,字段名称并不总是贴切的。有些情况下,你可能想自定义一个标签。 你只需在模块中指定verbose_name。

举个例子,说明如何将Author.email的标签改为e-mail,中间有个横线。
增加verbose_name=’e-mail’

class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField(blank=True, verbose_name='e-mail') #blank=True allows email to be null

    # Add the string representation of the model
    def __unicode__(self):
        return u'%s %s' % (self.first_name, self.last_name)

这时,就变成了下面这个样子:
这里写图片描述

请注意,你不必把verbose_name的首字母大写,除非是连续大写(如:”USA state”)。Django会自动适时将首字母大写,并且在其它不需要大写的地方使用verbose_name的精确值。

最后还需注意的是,为了使语法简洁,你可以把它当作固定位置的参数传递。 这个例子与上面那个的效果相同。

class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField('e-mail',  blank=True)

但这不适用于ManyToManyField 和ForeignKey字段,因为它们第一个参数必须是模块类。 那种情形,必须显式使用verbose_name这个参数名称。

比如下面的代码中,
authors = models.ManyToManyField(Author)
第一个参数是模块类Author
如果要自定义字段标签就需要显式使用verbose_name

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)

    # Add the string representation of the module
    def __unicode__(self):
        return self.title

自定义ModelAdmin类

迄今为止,我们做的blank=True、null=True和verbose_name修改其实是模块级别,而不是管理级别的。 也就是说,这些修改实质上是构成模块的一部分,并且正好被管理工具使用,而不是专门针对管理工具的。

除了这些,Django还提供了大量选项让你针对特别的模块自定义管理工具。 这些选项都在ModelAdmin classes里面,这些类包含了管理工具中针对特别模块的配置。

自定义列表

让我们更深一步:自定义Author模块的列表中的显示字段。 列表默认地显示查询结果中对象的__unicode__()。 在第五章中,我们定义Author对象的__unicode__()方法,用以同时显示作者的姓和名。
books/models.py里的class Author
这里写图片描述

books/admin.py里注册Author模块
这里写图片描述

在admin中显示效果
即 列表默认地显示查询结果中对象的__unicode__()。 在第五章中,我们定义Author对象的__unicode__()方法,用以同时显示作者的姓和名。
这里写图片描述

再看看books这个app的admin的效果
这里写图片描述

对应的books/models.py代码

from django.db import models

# Create your models here.

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)
    country = models.CharField(max_length=50)
    website = models.URLField()

    #Add the string representation of the module
    #__unicode__() method tells Python how to display the object in unicode mode
    def __unicode__(self):
       return self.name

    #Specifies the default ordering of the model objects
    class Meta:
        ordering = ['name']


class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField(blank=True, verbose_name='e-mail') #blank=True allows email to be null

    # Add the string representation of the model
    def __unicode__(self):
        return u'%s %s' % (self.first_name, self.last_name)


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)

    # Add the string representation of the module
    def __unicode__(self):
        return self.title

可以看到admin管理工具自动给每个模块名称加了s, 如Author ->Authors
并且给模块首字母改为大写
看下面的例子就明白了
这里写图片描述

所对应的books/models.py代码
class aaaaauthor代码

class aaaaauthor(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField(blank=True, verbose_name='e-mail') #blank=True allows email to be null

    # Add the string representation of the model
    def __unicode__(self):
        return u'%s %s' % (self.first_name, self.last_name)

books/models.py完整代码

from django.db import models

# Create your models here.

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)
    country = models.CharField(max_length=50)
    website = models.URLField()

    #Add the string representation of the module
    #__unicode__() method tells Python how to display the object in unicode mode
    def __unicode__(self):
       return self.name

    #Specifies the default ordering of the model objects
    class Meta:
        ordering = ['name']


class aaaaauthor(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField(blank=True, verbose_name='e-mail') #blank=True allows email to be null

    # Add the string representation of the model
    def __unicode__(self):
        return u'%s %s' % (self.first_name, self.last_name)


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

    # Add the string representation of the module
    def __unicode__(self):
        return self.title

现在回到自定义列表这个正题:
我们可以在这基础上改进,添加其它字段,从而改变列表的显示。 这个页面应该提供便利,比如说:在这个列表中可以看到作者的邮箱地址。如果能按照姓氏或名字来排序,那就更好了。

为了达到这个目的,我们将为Author模块定义一个ModelAdmin类。 这个类是自定义管理工具的关键,其中最基本的一件事情是允许你指定列表中的字段。 打开admin.py并修改:

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

**class AuthorAdmin(admin.ModelAdmin):**
    **list_display = ('first_name', 'last_name', 'email')**
    **search_fields = ('first_name', 'last_name')**

admin.site.register(Publisher)
**admin.site.register(Author, AuthorAdmin)**
admin.site.register(Book)

接下来对应的内容在参考书里说的比较详细,在这里就不重复了。

其中**引起来的部分是修改的内容
修改前:
这里写图片描述
修改后:
弄好了这个东东,再刷新author列表页面,你会看到列表中有三列:姓氏、名字和邮箱地址。 另外,点击每个列的列头可以对那列进行排序。
这里写图片描述

接下来,让我们为Book列表页添加一些过滤器
这里写图片描述

添加的代码:
list_filter = (‘publication_date’,)

class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'publisher', 'publication_date')
    list_filter = ('publication_date',)
    date_hierarchy = 'publication_date'
    ordering = ('-publication_date',)
    fields = ('title', 'authors', 'publisher')

另外一种过滤日期的方式是使用date_hierarchy选项,如:
date_hierarchy = ‘publication_date’

class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'publisher', 'publication_date')
    list_filter = ('publication_date',)
    **date_hierarchy = 'publication_date'**

这里写图片描述

请注意,date_hierarchy接受的是* 字符串* ,而不是元组。因为只能对一个日期型字段进行层次划分。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值