Django自动管理工具是django.contrib的一部分。django.contrib是一套庞大的功能集,它是Django基本代码的组成部分,Django框架就是由众多包含附加组件(add-on)的基本代码构成的。
管理工具是本书讲述django.contrib的第一个部分。从技术层面上讲,它被称作django.contrib.admin。django.contrib中其它可用的特性,如用户鉴别系统(django.contrib.auth)、支持匿名会话(django.contrib.sessioins)以及用户评注系统(django.contrib.comments)。
settings文件中:
INSTALLED_APPS中包含:
‘django.contrib.admin’
‘django.contrib.auth’
‘django.contrib.contenttypes’
‘django.contrib.sessions’
MIDDLEWARE_CLASSES中包含:
‘django.middleware.common.CommonMiddleware’
‘django.contrib.sessions.middleware.SessionMiddleware’
‘django.contrib.auth.middleware.AuthenticationMiddleware’
创建超级用户,将’django.contrib.auth’加入到INSTALLED_APPS后,才可使用如下命令进行创建:
python manage.py createsuperuser
注意:
在本例中,我们通过上述命令创建了一个超级用户,用户名是admin,密码是4062324zane
在urls.py文件中把URLconf的admin路径注释去掉,保证内容存在:
# Include these import statements...
from django.contrib import admin
admin.autodiscover()
# And include this URLpattern...
urlpatterns = patterns('',
# ...
(r'^admin/', include(admin.site.urls)),
# ...
)
在Django管理也中,每一种数据类型都有一个change list和edit list
- change list:显示数据库中所有的可用对象
- edit list:可以添加、更改和删除数据库中的记录
如果母语不是英语,可以添加本地语言配置,需要在settings.py中添加:
‘django.middleware.locale.LocaleMiddleware’
但是一定要保证它必须是在’django.contrib.sessions.middleware.SessionMiddleware’之后。
在管理页面中点击【用户】进入用户信息详细配置页面,在这个页面中可以对用户的全部信息进行配置,即相当于操作数据库中的auth_user表。
注意:
如果要修改用户的密码,必须点击密码字段下的“这个表单(change password form)”,而不是直接更改字段值中的哈希码。
在mysite/books目录下的admin.py文件中增加如下内容:
from django.contrib import admin
from books.models import Publisher, Author, Book
admin.site.register(Publisher)
admin.site.register(Author)
admin.site.register(Book)
注意:
需要重新启动runserver才能生效;
在Add book页面中http://127.0.0.1:8000/admin/books/book/add/
,外键publisher是用一个选择框显示,多对多字段author用一个多选框显示,点击两个字段后的绿色加号,可以添加相关记录。
当服务启动后,Django从urls.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。可以在/usr/local/lib/python2.7/dist-packages/django/contrib/
目录下查看它的模板、视图、URLpatterns。
如果想指定某个字段为可选,只需要修改models.py文件,在指定字段上加上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)
def __unicode__(self):
return u'%s %s' % (self.first_name, self.last_name)
注意:
所有字段都默认blank=False,默认不允许输入空值。
SQL指定空值叫做NULL,NULL可以表示为未知的、非法的、或其它程序指定的含义,NULL不等于空字符串,就像Python中None不同于空字符串一样。
这意味着某个字符型字段(eg:VARCHAR)的值不可能同时包含NULL和空字符串。
Djanog为了消除歧义,在CREATE TABLE语句时自动为每个字段显式加上NOT NULL:
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
)
;
如果想允许一个日期型(DateFiled、TimeFiled、DateTimeFiled)或数字型(IntegerField、DecimalField、FloatField)字段为空,需要使用null=True和blank=True,eg:
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)
将上述修改的内容同步到数据库,或者使用同步数据库,或者进入dbshell执行ALTER语句:
ALTER TABLE books_book ALTER COLUMN publication_date DROP NOT NULL;
使用数据库同步的方式:
首先想到是migrate命令,执行后提示:
#python manage.py migrate
Operations to perform:
Apply all migrations: admin, contenttypes, books, auth, sessions
Running migrations:
No migrations to apply.
Your models have changes that are not yet reflected in a migration, and so won't be applied.
Run 'manage.py makemigrations' to make new migrations, and then re-run 'manage.py migrate' to apply them.
根据上面提示的信息,貌似得先执行makemigrations生成对应的SQL语句后,再执行migrate,好吧:
#python manage.py makemigrations
Migrations for 'books':
0002_auto_20170516_2239.py:
- Change Meta options on publisher
- Alter field email on author
- Alter field publication_date on book
再执行:
# python manage.py migrate
Operations to perform:
Apply all migrations: admin, contenttypes, books, auth, sessions
Running migrations:
Rendering model states... DONE
Applying books.0002_auto_20170516_2239... OK
完成上述操作后,再去管理工具的Books里添加一个Publication date为空的记录,添加成功。
在编辑页面中,每个字段的标签都是从模块的字段名称生成的。
规则很简单: 用空格替换下划线;首字母大写。
例如:Book模块中publication_date的标签是Publication date。
如果这个时候我们想自定义一个标签,只需要在模块中指定verbose_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')
修改后,重启服务就可以看到效果了。
注意:
不必把verbose_name的首字母大写,除非是连续大写(如:”USA state”)。Django会自动适时将首字母大写,并且在其它不需要大写的地方使用verbose_name的精确值。
为了使语法简洁,可以把它当作固定位置的参数传递,eg:
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这个参数名称。
Django还提供了大量选项让你针对特别的模块自定义管理工具。 这些选项都在ModelAdmin classes里面,这些类包含了管理工具中针对特别模块的配置。
以第五章定义的Author对象为例,增加效果:
在这个列表中可以看到作者的邮箱地址,能够按姓氏或名字来排序。
为了达到这个目的,需要将Author模块定义一个ModelAdmin类,这个类是自动化管理工具的关键,其中最基本的一件事情是允许你指定列表中的字段。
修改admin.py:
from django.contrib import admin
from books.models import Publisher, Author, Book
# Register your models here.
class AuthorAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name', 'email')
admin.site.register(Publisher)
admin.site.register(Author, AuthorAdmin)
admin.site.register(Book)
解释一下代码:
我们新建了一个类AuthorAdmin,它是从django.contrib.admin.ModelAdmin派生出来的子类,保存着一个类的自定义配置,以供管理工具使用。我们只自定义了一项:list_display, 它是一个字段名称的元组,用于列表显示。当然,这些字段名称必须是模块中有的。
我们修改了admin.site.register()调用,在Author后面添加了AuthorAdmin。你可以这样理解:用AuthorAdmin选项注册Author模块。
admin.site.register()函数接受一个ModelAdmin子类作为第二个参数。如果你忽略第二个参数,Django将使用默认的选项。Publisher和Book的注册就属于这种情况。
最终效果:
再刷新author列表页面,你会看到列表中有三列:姓氏、名字和邮箱地址。 另外,点击每个列的列头可以对那列进行排序。
再增加一个快速查询栏:
class AuthorAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name', 'email')
search_fields = ('first_name', 'last_name')
注意:
搜索框对大小写敏感,并且对两个字段检索的查询框,比如查询”bar”,那么名字中包含有Barney和姓氏中含有Hobarson的作者记录将被检索出来。
再增加一个过滤器:
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'publisher', 'publication_date')
list_filter = ('publication_date',)
注意:
使用list_filter这个字段元组创建过滤器,这个过滤器同样适用于其他类型的字段,而不单是日期型,还可以是布尔型、外键等。
再增加另外一种日期的过滤方式:
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'publisher', 'publication_date')
list_filter = ('publication_date',)
#list_filter = ('publisher',)
date_hierarchy = 'publication_date'
注意:
在页面中的列表顶端会有一个逐层深入的导航条,从可用的年份开始,然后逐层细分到月乃至日。
date_hierarchy接受的是字符串而不是元组,切记。因为它只能对一个日期型字段进行层次划分。
默认情况date_hierarchy是降序排列,列表页面默认按照模块class Meta中的ordering所指的列排序,但目前没有指定ordering的值,所以当前排序是没有定义的,修改admin.py代码如下:
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'publisher', 'publication_date')
list_filter = ('publication_date',)
#list_filter = ('publisher',)
date_hierarchy = 'publication_date'
ordering = ('-publication_date',)
这个ordering选项基本像模块中class Meta的ordering那样工作,除了它只用列表中的第一个字段名,如果要实现降序,仅需在传入的列表或元组的字段前加上一个减号(-)。
正如自定义列表那样,编辑表单多方面也能自定义。
默认表单中的字段顺序是与模块中定义是一致的,我们可以通过使用ModelAdmin子类中的fields选项来改变它:
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'publisher', 'publication_date')
list_filter = ('publication_date',)
#list_filter = ('publisher',)
date_hierarchy = 'publication_date'
ordering = ('-publication_date',)
fields = ('title', 'authors', 'publisher', 'publication_date')
完成后,编辑表单时,注意是编辑表单,而不是列表查看页面,编辑表单页面将安装指定的顺序显示各字段,效果如图:
通过fields这个选项,可以排除一些不想显示出来的字段,只需要将其从fields里删除即可,比如我们隐藏publication_date这个字段,防止它被编辑:
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'publisher', 'publication_date')
list_filter = ('publication_date',)
#list_filter = ('publisher',)
date_hierarchy = 'publication_date'
ordering = ('-publication_date',)
fields = ('title', 'authors', 'publisher')
这样,在编辑页面就无法对publication_date字段进行改动,效果如下:
注意:
当用户没有权限编辑publication_date字段时,此时添加的表单,Django会简单地将publication_date设置为None,以确保整个字段满足null=True的条件。
针对编辑页面中的多对多字段自定义的方法是使用filter_horizontal,将其添加到BookAdmin中:
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'publisher', 'publication_date')
list_filter = ('publication_date',)
#list_filter = ('publisher',)
date_hierarchy = 'publication_date'
ordering = ('-publication_date',)
#fields = ('title', 'authors', 'publisher', 'publication_date')
filter_horizontal = ('authors',)
刷新book编辑页面,你会看到Author区中有一个精巧的JavaScript过滤器,它允许你检索选项,然后将选中的authors从Available框移到Chosen框,还可以移回来,效果如下:
注意:
建议对拥有是个以上选项的多对多字段都使用这种filter_horizontal。可以在多个字段使用该方法,只需要把列表或元组名加入其中。
除此之外,ModelAdmin类还支持filter_vertical选项,工作原理同filter_horizontal,只是控件是垂直排列。
filter_horizontal和filter_vertical选项只能用在多对多字段上,不能用于ForeignKey字段。
默认情况,管理工具使用“下拉框”来展现“外键”字段。
如果book数据库包含的数据非常多,拥有数千条publishers的记录的时候,就会导致book的添加页面装载publisher的时间会很久,因为它必须把每一个publisher都装载并显示在下拉框中,为解决这个问题,必须使用raw_id_fields选项,它是一个包含外键字段名称的元组,它包含的字段将被展现成“文本框”,而不是“下拉框”:
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'publisher', 'publication_date')
list_filter = ('publication_date',)
date_hierarchy = 'publication_date'
ordering = ('‐publication_date',)
filter_horizontal = ('authors',)
raw_id_fields = ('publisher',)
注意:
在这个输入框里输入的数字,其实是publisher的数据库ID号,点击旁边的小放大镜图标,可以添加publisher。
管理工具有一个权限系统,通过它你可以根据用户的需要来指定他们的权限,从而达到部分访问系统的目的。
用户对象有标准的用户名、密码、邮箱地址和真实姓名,同时它还有关于使用
管理界面的权限定义。首先,这有一组三个布尔型标记:
活动标志,它用来控制用户是否已经激活。如果一个用户帐号的这个标记是关闭状态,而用户又尝试用它登录时,即使密码正确,他也无法登录系统。
成员标志,它用来控制这个用户是否可以登录管理界面(即:这个用户是不是你们组织里的成员)由于用户系统可以被用户控制公众页面(即:非管理页面)的访问权限,这个标志可用来区分公众用户和管理用户。
超级用户标志,它赋予用户在管理界面中添加、修改和删除任何项目的权限,如果一个用户账号有这个标志,那么所有权限设置都会被忽略。
当创建一个用户时,它没有任何权限,该有什么权限是由你决定的,eg:可以给一个用户添加和修改publishers的权限,而不给他删除的权限。
注意:
这些权限都是定义在模块级别上的,而不是对象级别上。eg:用户小强可以修改任何图书,但是不能让他修改机械工业出版社出版的图书。
权限管理系统也控制编辑用户和权限。如果你给某人编辑用户的权限,他可以编辑自己的权限,这种能力可能不是你希望的。赋予一个用户修改用户的权限,本质上说就是把他变成一个超级用户。
你也可以给组中分配用户。 一个组简化了给组中所有成员应用一套许可的动作。 组在给大量用户特定权限的时候很有用。
Django的管理界面对非技术用户要输入他们的数据特别有用。除了数据输入方面,管理界面在下面这些清净中也是很有用的:
模块检查:当你定义好了若干个模块,在管理页面中把他们调出来然后输入一些虚假的数据,这是相当有用的,有时候,它能显示数据建模的错误或者模块中其它问题。
管理既得数据:如果你的应用程序依赖外部数据(来自用户输入或网络爬虫),管理界面提供了一个便捷的途径,让你检查和编辑那些数据,你可以把它看作是一个功能不那么强大但是很方便的数据库命令行工具。
临时的数据管理程序:你可以用管理工具建立自己的轻量级数据管理程序,比如说开销记录。如果你正在根据自己的,而不是公众的需要开发些什么,那么管理界面可以带给你很大的帮助。从这个意义上讲,你可以把它看作是一个增强的关系型电子表格。
管理页面不是终结者,它不应该被拆分、修改成若干个功能模块,而这些功能不是它所支持的,它不应该成为一个公众数据访问接口,也不应允许对你的数据进行复杂的排序和查询,它仅提供给可信任的管理员。请记住这一点,它是有效使用管理界面的钥匙。