django的后台我们只要加少些代码,就可以实现强大的功能。
与后台相关文件:每个app中的 admin.py 文件与后台相关。
下面示例是做一个后台添加博客文章的例子:
1
|
django-admin.py startproject zqxt_admin
|
1
2
3
4
5
|
# 进入 zqxt_admin 文件夹
cd
zqxt_admin
# 创建 blog 这个 app
python manage.py startapp blog
|
注意:不同版本的 Django 创建 project 和 app 出来的文件会有一些不同
1
2
3
4
5
6
7
8
9
10
|
# coding:utf-8
from
django.db
import
models
class
Article(models.Model):
title
=
models.CharField(u
'标题'
, max_length
=
256
)
content
=
models.TextField(u
'内容'
)
pub_date
=
models.DateTimeField(u
'发表时间'
, auto_now_add
=
True
, editable
=
True
)
update_time
=
models.DateTimeField(u
'更新时间'
,auto_now
=
True
, null
=
True
)
|
1
2
3
4
5
6
7
8
9
10
|
INSTALLED_APPS
=
(
'django.contrib.admin'
,
'django.contrib.auth'
,
'django.contrib.contenttypes'
,
'django.contrib.sessions'
,
'django.contrib.messages'
,
'django.contrib.staticfiles'
,
'blog'
,
)
|
提示:INSTALLED_APPS 是一个元组,每次加入新的app的时候,在后面都加一个逗号,这是一个好习惯。
1
2
3
4
5
6
|
# 进入包含有 manage.py 的文件夹
python manage.py makemigrations
python manage.py migrate
注意:Django 1.6.x 及以下的版本需要用以下命令
python manage.py syncdb
|
可以看到:
Creating tables ...
Creating table django_admin_log
Creating table auth_permission
Creating table auth_group_permissions
Creating table auth_group
Creating table auth_user_groups
Creating table auth_user_user_permissions
Creating table auth_user
Creating table django_content_type
Creating table django_session
Creating table blog_article
You just installed Django's auth system, which means you don't have any superusers defined.
Would you like to create one now? (yes/no): yes
Username (leave blank to use 'tu'): tu
Email address:
Password:
Password (again):
Superuser created successfully.
Installing custom SQL ...
Installing indexes ...
Installed 0 object(s) from 0 fixture(s)
如果是 Django 不主动提示创建管理员(Django 1.9不提示)用下面的命令创建一个帐号
1
|
python manage.py createsuperuser
|
进入 blog 文件夹,修改 admin.py 文件(如果没有新建一个),内容如下
1
2
3
4
5
|
from
django.contrib
import
admin
from
.models
import
Article
admin.site.register(Article)
|
只需要这三行代码,我们就可以拥有一个强大的后台!
提示:urls.py中关于 admin的已经默认开启,如果没有,参考这里。
1
2
|
python manage.py runserver
# 如果提示 8000 端口已经被占用,可以用 python manage.py runserver 8001 以此类推
|
访问 http://localhost:8000/admin/ 输入设定的帐号和密码, 就可以看到:
点击 Articles,动手输入 添加几篇文章,就可以看到:
我们会发现所有的文章都是叫 Article object,这样肯定不好,比如我们要修改,如何知道要修改哪个呢?
我们修改一下 blog 中的models.py
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# coding:utf-8
from
django.db
import
models
class
Article(models.Model):
title
=
models.CharField(u
'标题'
, max_length
=
256
)
content
=
models.TextField(u
'内容'
)
pub_date
=
models.DateTimeField(u
'发表时间'
, auto_now_add
=
True
, editable
=
True
)
update_time
=
models.DateTimeField(u
'更新时间'
,auto_now
=
True
, null
=
True
)
def
__unicode__(
self
):
# 在Python3中用 __str__ 代替 __unicode__
return
self
.title
|
我们加了一个 __unicode__ 函数,刷新后台网页,会看到:
所以推荐定义 Model 的时候 写一个 __unicode__ 函数(或 __str__函数)
技能提升:如何兼容python2.x和python3.x呢?
示例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# coding:utf-8
from __future__ import unicode_literals
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
@python_2_unicode_compatible
class Article(models.Model):
title = models.CharField(
'标题'
, max_length=256)
content = models.TextField(
'内容'
)
pub_date = models.DateTimeField(
'发表时间'
, auto_now_add=True, editable = True)
update_time = models.DateTimeField(
'更新时间'
,auto_now=True, null=True)
def __str__(self):
return
self.title
|
python_2_unicode_compatible 会自动做一些处理去适应python不同的版本,本例中的 unicode_literals 可以让python2.x 也像 python3 那个处理 unicode 字符,以便有更好地兼容性。
后台已经基本上做出来了,可是如果我们还需要显示一些其它的fields,如何做呢?
1
2
3
4
5
6
7
|
from
django.contrib
import
admin
from
.models
import
Article
class
ArticleAdmin(admin.ModelAdmin):
list_display
=
(
'title'
,
'pub_date'
,
'update_time'
,)
admin.site.register(Article,ArticleAdmin)
|
list_display 就是来配置要显示的字段的,当然也可以显示非字段内容,或者字段相关的内容,比如:
1
2
3
4
5
6
7
8
9
|
class
Person(models.Model):
first_name
=
models.CharField(max_length
=
50
)
last_name
=
models.CharField(max_length
=
50
)
def
my_property(
self
):
return
self
.first_name
+
' '
+
self
.last_name
my_property.short_description
=
"Full name of the person"
full_name
=
property
(my_property)
|
在admin.py中
1
2
3
4
5
6
7
8
9
10
11
12
13
|
from
django.contrib
import
admin
from
.models
import
Article, Person
class
ArticleAdmin(admin.ModelAdmin):
list_display
=
(
'title'
,
'pub_date'
,
'update_time'
,)
class
PersonAdmin(admin.ModelAdmin):
list_display
=
(
'full_name'
,)
admin.site.register(Article, ArticleAdmin)
admin.site.register(Person, PersonAdmin)
|
到这里我们发现我们又有新的需求,比如要改 models.py 中的字段,添加一个文章的状态(草稿,正式发布),这时候我们就需要更改表,django 1.7以前的都不会自动更改表,我们需要用第三方插件 South,参见 Django 迁移数据。
Django 1.7 及以上用以下命令来同步数据库表的更改
1
2
|
python manage.py makemigrations
python manage.py migrate
|
本节代码下载:
zqxt_admin (Django 1.6).zip (基于Django 1.6,后台帐号 tu 密码 zqxt)
zqxt_admin (Django 1.9).zip (基于 Django 1.9 后台帐号 tu 密码 ziqiangxuetang)
其它一些常用的功能:
搜索功能:search_fields = ('title', 'content',) 这样就可以按照 标题或内容搜索了
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields
筛选功能:list_filter = ('status',) 这样就可以根据文章的状态去筛选,比如找出是草稿的文章
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_filter
新增或修改时的布局顺序:https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.fieldsets
有时候我们需要对django admin site进行修改以满足自己的需求,那么我们可以从哪些地方入手呢?
以下举例说明:
1.定制加载的列表, 根据不同的人显示不同的内容列表,比如输入员只能看见自己输入的,审核员能看到所有的草稿,这时候就需要重写get_queryset方法
1
2
3
4
5
6
7
|
class
MyModelAdmin(admin.ModelAdmin):
def
get_queryset(
self
, request):
qs
=
super
(MyModelAdmin,
self
).get_queryset(request)
if
request.user.is_superuser:
return
qs
else
:
return
qs.
filter
(author
=
request.user)
|
该类实现的功能是如果是超级管理员就列出所有的,如果不是,就仅列出访问者自己相关的
2.定制搜索功能(django 1.6及以上才有)
1
2
3
4
5
6
7
8
9
10
11
12
|
class
PersonAdmin(admin.ModelAdmin):
list_display
=
(
'name'
,
'age'
)
search_fields
=
(
'name'
,)
def
get_search_results(
self
, request, queryset, search_term):
queryset, use_distinct
=
super
(PersonAdmin,
self
).get_search_results(request, queryset, search_term)
try
:
search_term_as_int
=
int
(search_term)
queryset |
=
self
.model.objects.
filter
(age
=
search_term_as_int)
except
:
pass
return
queryset, use_distinct
|
queryset 是默认的结果,search_term 是在后台搜索的关键词
3.修改保存时的一些操作,可以检查用户,保存的内容等,比如保存时加上添加人
1
2
3
4
5
6
|
from
django.contrib
import
admin
class
ArticleAdmin(admin.ModelAdmin):
def
save_model(
self
, request, obj, form, change):
obj.user
=
request.user
obj.save()
|
其中obj是修改后的对象,form是返回的表单(修改后的),当新建一个对象时 change = False, 当修改一个对象时 change = True
如果需要获取修改前的对象的内容可以用
1
2
3
4
5
6
7
|
from
django.contrib
import
admin
class
ArticleAdmin(admin.ModelAdmin):
def
save_model(
self
, request, obj, form, change):
obj_original
=
self
.model.objects.get(pk
=
obj.pk)
obj.user
=
request.user
obj.save()
|
那么又有问题了,这里如果原来的obj不存在,也就是如果我们是新建的一个怎么办呢,这时候可以用try,except的方法尝试获取,当然更好的方法是判断一下这个对象是新建还是修改,是新建就没有 obj_original,是修改就有
1
2
3
4
5
6
7
8
9
10
11
|
from
django.contrib
import
admin
class
ArticleAdmin(admin.ModelAdmin):
def
save_model(
self
, request, obj, form, change):
if
change:
# 更改的时候
obj_original
=
self
.model.objects.get(pk
=
obj.pk)
else
:
# 新增的时候
obj_original
=
None
obj.user
=
request.user
obj.save()
|
4, 删除时做一些处理,
1
2
3
4
5
6
7
8
9
|
from
django.contrib
import
admin
class
ArticleAdmin(admin.ModelAdmin):
def
delete_model(
self
, request, obj):
"""
Given a model instance delete it from the database.
"""
# handle something here
obj.delete()
|
Django的后台非常强大,这个只是帮助大家入门,更完整的还需要查看官方文档,如果你有更好的方法或不懂的问题,欢迎评论!
参考:官方文档