Django后台管理界面

以前的几篇记录了模板视图、模型等页面展现的相关内容,这篇主要写一下后台admin管理界面的内容。html

激活管理界面

Django管理站点彻底是可选择的,以前咱们是把这些功能给屏蔽掉了。记得上篇中Django模型模型安装小结中,咱们把settings.py中的部份内容屏蔽了,并添加了一个app,以下python

 1 INSTALLED_APPS = (
 2 ##    'django.contrib.admin',
 3 ##    'django.contrib.auth',
 4 ##    'django.contrib.contenttypes',
 5 ##    'django.contrib.sessions',
 6 ##    'django.contrib.messages',
 7 ##    'django.contrib.staticfiles',
 8     'mysite.books',
 9 )
10 
11 MIDDLEWARE_CLASSES = (
12 ##    'django.contrib.sessions.middleware.SessionMiddleware',
13 ##    'django.middleware.common.CommonMiddleware',
14 ##    'django.middleware.csrf.CsrfViewMiddleware',
15 ##    'django.contrib.auth.middleware.AuthenticationMiddleware',
16 ##    'django.contrib.messages.middleware.MessageMiddleware',
17 ##    'django.middleware.clickjacking.XFrameOptionsMiddleware',
18 )

django.contrib.admin等这些就是支持后台admin管理界面的app,咱们将上边这些注释所有去掉,便可增长对后台管理界面的支持。shell

运行 python manage.py syncdb 。这一步将生成管理界面使用的额外数据库表。 当你把'django.contrib.auth'加进INSTALLED_APPS后,第一次运行syncdb命令时, 系统会请你建立一个超级用户。 若是你不这么做,你须要运行python manage.py createsuperuser来另外建立一个admin的用户账号,不然你将不能登入admin (提醒一句: 只有当INSTALLED_APPS包含'django.contrib.auth'时,python manage.py createsuperuser这个命令才可用.)数据库

到这里,咱们就把后台管理基本配置好了。可是想一想,咱们还差什么没作?django

时刻记得,去urls.py进行配置哦,下图是新建的project初始时候的URLConf,在Django创建helloworld自定义页面里咱们删除掉的内容session

 1 from django.conf.urls import patterns, include, url
 2 
 3 from django.contrib import admin
 4 
 5 admin.autodiscover()
 6 
 7 urlpatterns = patterns('',
 8     # Examples:
 9     # url(r'^$', 'testsite.views.home', name='home'),
10     # url(r'^blog/', include('blog.urls')),
11 
12     url(r'^admin/', include(admin.site.urls)),
13                        
14 )

如今,咱们要访问admin了,添加回来这几句吧app

from django.contrib import admin
admin.autodiscover()
url(r'^admin/', include(admin.site.urls)),

好,咱们运行起来看看吧。效果以下:函数

输入以前你添加的管理员帐户和密码,登录网站后台看看吧工具

若是你的母语不是英语,你能够作一个快速更改来观察Django管理工具是否被翻译成你想要的语言。 仅需添加 ‘django.middleware.locale.LocaleMiddleware’ 到 MIDDLEWARE_CLASSES 设置中,并确保它在’django.contrib.sessions.middleware.SessionMiddleware’后边(其实前后是不要紧的)。以下我放在了第一个位置。post

1 MIDDLEWARE_CLASSES = (
2     'django.middleware.locale.LocaleMiddleware',
3     'django.contrib.sessions.middleware.SessionMiddleware',
4     'django.middleware.common.CommonMiddleware',
5     'django.middleware.csrf.CsrfViewMiddleware',
6     'django.contrib.auth.middleware.AuthenticationMiddleware',
7     'django.contrib.messages.middleware.MessageMiddleware',
8     'django.middleware.clickjacking.XFrameOptionsMiddleware',
9 )

刷新一个刚才的页面,看看效果。

具体的使用,无非就是增删改查了,本身去点吧。

将自定义的Models加入到Admin管理中

上一篇Django模型-数据库操做,咱们定义了三个模块:Publisher 、 Author 和 Book 。 让咱们将本身的模块加入管理工具中,这样咱们就可以经过这个后台管理界面添加、修改和删除数据库中的对象了。

还记得新建的books app初始化的几个文件吗?

打开admin.py,添加内容以下

1 from django.contrib import admin
2 
3 # Register your models here.
4 from mysite.books.models import Publisher, Author, Book
5 
6 admin.site.register(Publisher)
7 admin.site.register(Author)
8 admin.site.register(Book)

这些代码通知管理工具为这些模块逐一提供界面。你可能须要先中止,而后再启动服务(runserver),才能使其生效。

 点开新加的三个模块,点开Books,外键publisher用一个选择框显示,多对多字段author用一个多选框显示,日期字段也是datepicker样式的选择,有没有很强大。

Admin是如何工做的

当服务启动时,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能在管理工具中自动显示。 

字段设置

咱们尝试添加一个做者信息,发现一些现象,每一个字段都是必填项,Email也有专门的格式验证。若是咱们不想要这些限制,该怎么作呢?

修改咱们的models.py以下

1 class Author(models.Model):
2     first_name = models.CharField(max_length=30)
3     last_name = models.CharField(max_length=40)
4     email = models.EmailField(blank=True)
5     
6     def __unicode__(self):
7         return u'%s %s' % (self.first_name,self.last_name)

标红部分是新添加的属性,这些代码告诉Django,做者的邮箱地址容许输入一个空值。

全部字段都默认blank=False,这使得它们不容许输入空值。

刷新页面,将会发现Email的标签再也不是粗体,这意味它不是一个必填字段。

 针对日期和数字的设置

Django生成CREATE TABLE语句自动为每一个字段显式加上NOT NULL,在大多数状况下,这种默认的行为对你的应用程序来讲是最佳的(消除NULL和空字符串的数据不一致)。

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

若是你想容许一个日期型(DateFieldTimeFieldDateTimeField)或数字型(IntegerFieldDecimalFieldFloatField)字段为空,你须要使用null=True  和 blank=True

添加null=True比添加blank=True复杂。由于null=True改变了数据的语义,即改变了CREATE TABLE语句,把publication_date字段上的NOT NULL删除了。 要完成这些改动,咱们还须要更新数据库。然而Django不会尝试自动更新数据库结构,因此你必须执行ALTER TABLE语句将模块的改动更新至数据库。

使用manage.py dbshell进入数据库服务环境,执行命令

ALTER TABLE books_book ALTER COLUMN publication_date DROP NOT NULL;

如今回到管理工具,添加book的编辑页面就容许输入一个空的publication date。

 日期和数字的设置这部分,因为我本地环境问题,manage.py  dbshell总有问题,因此该部份内容,我没进行相应操做。
 我本地的搜索路径以下,是否是缺乏Sqlite3的命令路径?有大牛知道的,请告知,谢谢! 

自定义字段标签

在编辑页面中,每一个字段的标签都是从模块的字段名称生成的。规则很简答:用空格替换下划线;首字母大写。好比上边新增做者的那个截图:first_name变成了First name。

有些状况下,咱们想展现自定的标签名。为作到这个,咱们只须要在models的模块定义中指定verbose_name便可。

好比咱们要将Author.email的标签改为e-mail,中间有个横线,能够这样作

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

从新启动服务,刷新页面,效果以下

最后还需注意的是,为了使语法简洁,你能够把它看成固定位置的参数传递。 这个例子与上面那个的效果相同。
1 class Author(models.Model):
2     first_name = models.CharField(max_length=30)
3     last_name = models.CharField(max_length=40)
4     email = models.EmailField('e-mail',  blank=True)

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

自定义ModelAdmin类

咱们作的 blank=Truenull=Trueverbose_name修改实际上是模块级别,而不是管理级别的。 也就是说,这些修改实质上是构成模块的一部分,而且正好被管理工具使用,而不是专门针对管理工具的。除了这些,Django还提供了大量选项让你针对特别的模块自定义管理工具。 这些选项都在 ModelAdmin classes里面,这些类包含了管理工具中针对特别模块的配置。

自定义列表

让咱们更深一步:自定义 Author模块的列表中的显示字段。 列表默认地显示查询结果中对象的 __unicode__()
1 class Author(models.Model):
2     first_name = models.CharField(max_length=30)
3     last_name = models.CharField(max_length=40)
4     email = models.EmailField(blank=True,verbose_name='e-mail')
5 
6     def __unicode__(self):
7         return u'%s %s' % (self.first_name,self.last_name)

咱们能够在这基础上改进,添加其它字段,从而改变列表的显示。 这个页面应该提供便利,好比说:在这个列表中能够看到做者的邮箱地址。若是能按照姓氏或名字来排序,那就更好了。

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

 1 from django.contrib import admin
 2 from models import *
 3 
 4 # Register your models here.
 5 
 6 class AuthorAdmin(admin.ModelAdmin):
 7     list_display = ('first_name', 'last_name', 'email')
 8     
 9 admin.site.register(Publisher)
10 admin.site.register(Author,AuthorAdmin)
11 admin.site.register(Book)

咱们新建了一个类AuthorAdmin,它是从django.contrib.admin.ModelAdmin派生出来的子类,保存着一个类的自定义配置,以供管理工具使用。 咱们只自定义了一项:list_display, 它是一个字段名称的元组,用于列表显示。 固然,这些字段名称必须是模块中有的

咱们修改了 admin.site.register()调用,在 Author后面添加了 AuthorAdmin。你能够这样理解: 用 AuthorAdmin选项注册 Author模块。
admin.site.register()函数接受一个 ModelAdmin子类做为第二个参数。 若是你忽略第二个参数,Django将使用默认的选项。 PublisherBook的注册就属于这种状况。
 
刷新author列表页面,你会看到列表中有三列:姓氏、名字和邮箱地址。 另外,点击每一个列的列头能够对那列进行排序。
 
让咱们再添加一个快速查询栏。 向 AuthorAdmin追加 search_fields,如:
1 class AuthorAdmin(admin.ModelAdmin):
2     list_display = ('first_name', 'last_name', 'email')
3     search_fields = ('first_name', 'last_name')

刷新页面,效果以下

 
接下来,为Book列表页添加一些过滤器,以下
 1 from django.contrib import admin
 2 from models import *
 3 
 4 # Register your models here.
 5 
 6 class AuthorAdmin(admin.ModelAdmin):
 7     list_display = ('first_name', 'last_name', 'email')
 8     search_fields = ('first_name', 'last_name')
 9 
10 class BookAdmin(admin.ModelAdmin):
11     list_display=('title','publisher','publication_date')
12     list_filter=('publication_date',)
13     
14 admin.site.register(Publisher)
15 admin.site.register(Author,AuthorAdmin)
16 admin.site.register(Book,BookAdmin)

刷新效果以下:

list_filter这个字段元组建立过滤器,它位于列表页面的右边。 Django为日期型字段提供了快捷过滤方式,它包含:今天、过往七天、当月和今年。
另一种过滤日期的方式是使用 date_hierarchy选项,如:
1 class BookAdmin(admin.ModelAdmin):
2     list_display=('title','publisher','publication_date')
3     list_filter=('publication_date',)
4     date_hierarchy = 'publication_date'

修改好后,页面中的列表顶端会有一个逐层深刻的导航条,效果如图 6-11. 它从可用的年份开始,而后逐层细分到月乃至日。

查看结果以下

请注意, date_hierarchy接受的是* 字符串* ,而不是元组。由于只能对一个日期型字段进行层次划分。
 
最后,让咱们改变默认的排序方式,按publication date降序排列。 列表页面默认按照模块 class Meta中的 ordering所指的列排序。详细请看 Django模型-数据库操做 。该实例中没有指定ordering,因此排序是没定义的。
1 class BookAdmin(admin.ModelAdmin):
2     list_display=('title','publisher','publication_date')
3     list_filter=('publication_date',)
4     date_hierarchy = 'publication_date'
5     ordering = ('-publication_date',)

这个ordering选项基本像模块中class Metaordering那样工做。效果是Publication date列头如今有一个小箭头显示排序。

自定义编辑表单

首先,咱们先自定义字段顺序。 默认地,表单中的字段顺序是与模块中定义是一致的。 咱们能够经过使用ModelAdmin子类中的fields选项来改变它:

1 class BookAdmin(admin.ModelAdmin):
2     list_display=('title','publisher','publication_date')
3     list_filter=('publication_date',)
4     date_hierarchy = 'publication_date'
5     ordering = ('-publication_date',)
6     fields = ('authors', 'title', 'publisher')

顺序是咱们自定义的,可编辑的字段也是咱们可选择的。效果以下:

此时新增记录,Django会简单地将publication_date设置为None,以确保这个字段知足null=True的条件。

由于以前我说的,本地的Python manage.py dbshell 失败,致使我没法修改数据库结构,

publication_date = models.DateField(blank=True,null=True)

这段代码是失效的,因此我在这里提交代码会出错,以下:

若是你本地的命令没问题,而且根据以前的说明修改了对应数据库字段可空(NULL和空字符串),则不会出错。

另外一个经常使用的编辑页面自定义是针对多对多字段的。 真如咱们在book编辑页面看到的那样, '多对多字段' 被展示成多选框。虽然多选框在逻辑上是最适合的HTML控件,但它却不那么好用。 若是你想选择多项,你必须还要按下Ctrl键。 虽然管理工具添加了注释(help_text),可是当它有几百个选项时,它依然显得笨拙。

更好的办法是使用filter_horizontal。让咱们把它添加到BookAdmin中,而后看看它的效果。

1 class BookAdmin(admin.ModelAdmin):
2     list_display=('title','publisher','publication_date')
3     list_filter=('publication_date',)
4     date_hierarchy = 'publication_date'
5     ordering = ('-publication_date',)
6     #fields = ('authors', 'title', 'publisher')
7     filter_horizontal = ('authors',)

效果以下

ModelAdmin类还支持filter_vertical选项。 它像filter_horizontal那样工做,除了控件都是垂直排列,而不是水平排列的。

filter_horizontalfilter_vertical选项只能用在多对多字段 上, 而不能用于 ForeignKey字段。 默认地,管理工具使用'下拉框' 来展示 外键 字段。下拉框选择就会将全部值加载到下拉列表,选中某个或许须要拖滚动条很久才能找到。

Django提供了raw_id_fields 选项,它是一个包含外键字段名称的元组,它包含的字段将被展示成’ 文本框‘和检索按钮的形式。

1 class BookAdmin(admin.ModelAdmin):
2     list_display=('title','publisher','publication_date')
3     list_filter=('publication_date',)
4     date_hierarchy = 'publication_date'
5     ordering = ('-publication_date',)
6     #fields = ('authors', 'title', 'publisher')
7     filter_vertical = ('authors',)
8     raw_id_fields = ('publisher',)

这个文框内可输入的值是publisher的id,经过检索弹框选择便可。

小结

这篇篇幅较长,内容很多。还有一部分关于权限的东西,这里很少说了,后台里多点点就能理解。