您的位置:首页 > 编程语言 > Go语言

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

2016-12-01 21:47 501 查看
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接受的是* 字符串* ,而不是元组。因为只能对一个日期型字段进行层次划分。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  django web框架 admin table