django的後臺我們只要加少些代碼,就可以實現強大的功能。
與後臺相關文件:每個app中的 admin.py 文件與後臺相關。
下面示例是做一個後臺添加博客文章的例子:
一,新建一個 名稱爲 zqxt_admin 的項目
1 | django-admin.py startproject zqxt_admin |
二,新建一個 叫做 blog 的app
1 2 3 4 5 | # 進入 zqxt_admin 文件夾 cd zqxt_admin # 創建 blog 這個 app python manage.py startapp blog |
注意:不同版本的 Django 創建 project 和 app 出來的文件會有一些不同
三,修改 blog 文件夾中的 models.py
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 ) |
四,把 blog 加入到settings.py中的INSTALLED_APPS中
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 |
六,修改 admin.py
進入 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',) 這樣就可以按照 標題或內容搜索了
篩選功能: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() |