1. 程式人生 > >DJANGO ADMIN後臺設定

DJANGO ADMIN後臺設定

Django自帶的後臺管理是Django明顯特色之一,可以讓我們快速便捷管理資料。後臺管理可以在各個app的admin.py檔案中進行控制。以下是我最近摸索總結出比較實用的配置。若你有什麼比較好的配置,歡迎補充。

 

一、基本設定

1、應用註冊

若要把app應用顯示在後臺管理中,需要在admin.py中註冊。這個註冊有兩種方式,我比較喜歡用裝飾器的方式。

先看看普通註冊方法。開啟admin.py檔案,如下程式碼:

1

2

3

4

5

6

7

8

9

from django.contrib import

 admin

from blog.models import Blog

  

#Blog模型的管理器

class BlogAdmin(admin.ModelAdmin):

    list_display=('id''caption''author''publish_time')

     

#在admin中註冊繫結

admin.site.register(Blog, BlogAdmin)

  上面方法是將管理器和註冊語句分開。有時容易忘記寫註冊語句,或者模型很多,不容易對應。

還有一種方式是用裝飾器,該方法是Django1.7的版本新增的功能:

1

2

3

4

5

6

7

from django.contrib import admin

from blog.models import Blog

  

#Blog模型的管理器

@admin.register(Blog)

class BlogAdmin(admin.ModelAdmin):

    list_display=('id''caption''author''publish_time')

  該方式比較方便明顯,推薦用這種方式。

 

2、admin介面漢化

預設admin後臺管理介面是英文的,對英語盲來說用起來不方便。可以在settings.py中設定:

  1. LANGUAGE_CODE = 'zh-CN'
  2. TIME_ZONE = 'Asia/Shanghai'

1.8版本之後的language code設定不同:

  1. LANGUAGE_CODE = 'zh-hans'
  2. TIME_ZONE = 'Asia/Shanghai'

 

二、記錄列表介面設定

記錄列表是我們開啟後臺管理進入到某個應用看到的介面,如下所示:

 

我們可以對該介面進行設定,主要包括列表和篩選器。

 

1、記錄列表基本設定

比較實用的記錄列表設定有顯示欄位、每頁記錄數和排序等。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

from django.contrib import admin

from blog.models import Blog

  

#Blog模型的管理器

@admin.register(Blog)

class BlogAdmin(admin.ModelAdmin):

    #listdisplay設定要顯示在列表中的欄位(id欄位是Django模型的預設主鍵)

    list_display = ('id''caption''author''publish_time')

    

    #list_per_page設定每頁顯示多少條記錄,預設是100條

    list_per_page = 50

    

    #ordering設定預設排序欄位,負號表示降序排序

    ordering = ('-publish_time',)

  

    #list_editable 設定預設可編輯欄位

    list_editable = ['machine_room_id''temperature']

  

    #fk_fields 設定顯示外來鍵欄位

     fk_fields = ('machine_room_id',)

  

此處比較簡單,自己嘗試一下即可。

 

另外,預設可以點選每條記錄第一個欄位的值可以進入編輯介面。 

 

我們可以設定其他欄位也可以點選連結進入編輯介面。

1

2

3

4

5

6

7

8

from django.contrib import admin

from blog.models import Blog

  

#Blog模型的管理器

@admin.register(Blog)

class BlogAdmin(admin.ModelAdmin):   

    #設定哪些欄位可以點選進入編輯介面

    list_display_links = ('id''caption')

  

2、篩選器

篩選器是Django後臺管理重要的功能之一,而且Django為我們提供了一些實用的篩選器。

主要常用篩選器有下面3個:

1

2

3

4

5

6

7

8

9

10

11

12

from django.contrib import admin

from blog.models import Blog

  

#Blog模型的管理器

@admin.register(Blog)

class BlogAdmin(admin.ModelAdmin):

    list_display = ('id''caption''author''publish_time')

     

    #篩選器

    list_filter =('trouble''go_time''act_man__user_name''machine_room_id__machine_room_name'#過濾器

    search_fields =('server''net''mark'#搜尋欄位

    date_hierarchy = 'go_time'    # 詳細時間分層篩選 

對應效果如下:

 此處注意:

使用  date_hierarchy  進行詳細時間篩選的時候 可能出現報錯:Database returned an invalid datetime value. Are time zone definitions for your database and pytz installed?

處理方法:  

命令列直接執行此命令:     [[email protected] ~]#    mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql

然後重啟資料庫即可。

 

一般ManyToManyField多對多欄位用過濾器;標題等文字欄位用搜索框;日期時間用分層篩選。

過濾器如果是外來鍵需要遵循這樣的語法:本表字段__外來鍵表要顯示的欄位。如:“user__user_name”

 

3、顏色顯示

想對某些欄位設定顏色,可用下面的設定:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

from django.db import models

from django.contrib import admin

from django.utils.html import format_html

 

class Person(models.Model):

    first_name = models.CharField(max_length=50)

    last_name = models.CharField(max_length=50)

    color_code = models.CharField(max_length=6)

 

    def colored_name(self):

        return format_html(

            '<span style="color: #{};">{} {}</span>',

            self.color_code,

            self.first_name,

            self.last_name,

        )

 

class PersonAdmin(admin.ModelAdmin):

    list_display = ('first_name''last_name''colored_name')

  

實際程式碼(注意看上面程式碼,是寫在models裡,而不是admin中的ModelAdmin裡):

 

效果:

 

但是,我們看到標題並不是我們想要的,那麼如何設定標題呢?

 

新增一行程式碼:colored_status.short_description = u"狀態"

 

在函式結束之後新增上面程式碼即可

 

 4.調整頁面頭部顯示內容和頁面標題

程式碼:

1

2

3

4

5

class MyAdminSite(admin.AdminSite):

    site_header = '好醫生運維資源管理系統'  # 此處設定頁面顯示標題

    site_title = '好醫生運維'  # 此處設定頁面頭部標題

 

admin_site = MyAdminSite(name='management')

  需要注意的是:  admin_site = MyAdminSite(name='management') 此處括號內name值必須設定,否則將無法使用admin設定許可權,至於設定什麼值,經本人測試,沒有影響。

註冊的時候使用admin_site.register,而不是預設的admin.site.register。

效果如下:

 後經網友提示發現也可以這樣:

1

2

3

4

5

6

7

8

9

10

11

12

from django.contrib import admin

from hys_operation.models import *

 

 

# class MyAdminSite(admin.AdminSite):

#     site_header = '好醫生運維資源管理系統'  # 此處設定頁面顯示標題

#     site_title = '好醫生運維'

#

# # admin_site = MyAdminSite(name='management')

# admin_site = MyAdminSite(name='adsff')

admin.site.site_header = '修改後'

admin.site.site_title = '哈哈'

  不繼承 admin.AdminSite 了,直接用admin.site 下的 site_header 和 site_title 。

更加簡單方便,容易理解。  唯一的區別就是 這種方法 是登入http://ip/admin/

 站點和使用者組在一起

而第一種方法是分開的。

 

5.通過當前登入的使用者過濾顯示的資料

官方文件的介紹:

 

 

實際程式碼和效果:

 

@admin.register(MachineInfo)

class MachineInfoAdmin(admin.ModelAdmin):

 

    def get_queryset(self, request):

        """函式作用:使當前登入的使用者只能看到自己負責的伺服器"""

        qs = super(MachineInfoAdmin, self).get_queryset(request)

        if request.user.is_superuser:

            return qs

        return qs.filter(user=UserInfo.objects.filter(user_name=request.user))

 

    list_display = ('machine_ip', 'application', 'colored_status', 'user', 'machine_model', 'cache',

                    'cpu', 'hard_disk', 'machine_os', 'idc', 'machine_group')
 

 

 

 

三、編輯介面設定

編輯介面是我們編輯資料所看到的頁面。我們可以對這些欄位進行排列設定等。

若不任何設定,如下圖所示:

 

這個介面比較簡陋,需要稍加設定即可。

 

1、編輯介面設定

首先多ManyToMany多對多欄位設定。可以用filter_horizontal或filter_vertical:

 
  1. #Many to many 欄位
  2. filter_horizontal=('tags',)

效果如下圖:

 

這樣對多對多欄位操作更方便。

另外,可以用fields或exclude控制顯示或者排除的欄位,二選一即可。

例如,我想只顯示標題、作者、分類標籤、內容。不想顯示是否推薦欄位,可以如下兩種設定方式:

 
  1. fields =  ('caption', 'author', 'tags', 'content')

或者

 
  1. exclude = ('recommend',) #排除該欄位

設定之後,你會發現這些欄位都是一個欄位佔一行。若想兩個欄位放在同一行可以如下設定:

 
  1. fields =  (('caption', 'author'), 'tags', 'content')

效果如下:

 

 

2、編輯欄位集合

不過,我不怎麼用fields和exclude。用得比較多的是fieldsets。該設定可以對欄位分塊,看起來比較整潔。如下設定:

 
  1. fieldsets = (
  2.     ("base info", {'fields': ['caption', 'author', 'tags']}),
  3.     ("Content", {'fields':['content', 'recommend']})
  4. )

效果如下:

 

 

3、一對多關聯

還有一種比較特殊的情況,父子表的情況。編輯父表之後,再開啟子表編輯,而且子表只能一條一條編輯,比較麻煩。

這種情況,我們也是可以處理的,將其放在同一個編輯介面中。

例如,有兩個模型,一個是訂單主表(BillMain),記錄主要資訊;一個是訂單明細(BillSub),記錄購買商品的品種和數量等。

admin.py如下:

 
  1. #coding:utf-8
  2. from django.contrib import admin
  3. from bill.models import BillMain, BillSub
  4.  
  5. @admin.register(BillMain)
  6. class BillMainAdmin(admin.ModelAdmin):
  7.     inlines = [BillSubInline,]    #Inline把BillSubInline關聯進來
  8.     list_display = ('bill_num', 'customer',)
  9.     
  10. class BillSubInline(admin.TabularInline):
  11.     model = BillSub
  12.     extra = 5 #預設顯示條目的數量

 

這樣就可以快速方便處理資料。

相關的admin比較有用的設定大致這些,若你覺得還有一些比較有用的,可以留意參與討論。

 

4.設定只讀欄位

 在使用admin的時候,ModelAdmin預設對於model的操作只有增加,修改和刪除,但是總是有些欄位是不希望使用者來編輯的。而 readonly_fields 設定之後不管是admin還是其他使用者都會變成只讀,而我們通常只是想限制普通使用者。 這時我們就可以通過重寫 get_readonly_fields 方法來實現對特定使用者的只讀顯示。

官網介紹:  (https://docs.djangoproject.com/en/1.10/ref/contrib/admin/#django.contrib.admin.ModelAdmin.readonly_fields

程式碼:

1

2

3

4

5

6

7

8

9

10

class MachineInfoAdmin(admin.ModelAdmin):

 

    def get_readonly_fields(self, request, obj=None):

        """  重新定義此函式,限制普通使用者所能修改的欄位  """

        if request.user.is_superuser:

            self.readonly_fields = []

        return self.readonly_fields

     

    readonly_fields = ('machine_ip''status''user''machine_model''cache',

                       'cpu''hard_disk''machine_os''idc''machine_group')

  效果:

 

 5、資料儲存時進行一些額外的操作(通過重寫ModelAdmin的save_model實現)

 

程式碼:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

def save_model(self, request, obj, form, change):

    """  重新定義此函式,提交時自動新增申請人和備案號  """

 

    def make_paper_num():

        """ 生成隨機備案號 """

        import datetime

        import random

        CurrentTime = datetime.datetime.now().strftime("%Y%m%d%H%M%S")  # 生成當前時間

        RandomNum = random.randint(0100)  # 生成的隨機整數n,其中0<=n<=100

        UniqueNum = str(CurrentTime) + str(RandomNum)

        return UniqueNum

 

    obj.proposer = request.user

    obj.paper_num = make_paper_num()

    super(DataPaperStoreAdmin, self).save_model(request, obj, form, change)

  這樣,在新增資料時,會自動儲存申請人和備案號。

 我們也可以在修改資料時獲取儲存前的資料:

通過change引數,可以判斷是修改還是新增,同時做相應的操作。上述程式碼就是在替換磁碟的時候修改狀態,並寫入日誌。

 程式碼:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

def save_model(self, request, obj, form, change):

    if change:  # 更改的時候

        machine_code = self.model.objects.get(pk=obj.pk).machine

        disk_id = self.model.objects.get(pk=obj.pk).disk_id

        disk_code = self.model.objects.get(pk=obj.pk).disk

        machine.Device.objects.filter(pk=disk_id).update(device_status='待報廢')

        data = {'server_code': machine_code,

                'device_type''硬碟',

                'original_code': disk_code,

                'way''變更',

                'current_code': obj.disk}

        common.DeLog.objects.create(**data)  # 建立日誌

    else:  # 新增的時候

        data = {'server_code': obj.machine,

                'device_type''硬碟',

                'original_code': '',

                'way''新增',

                'current_code': obj.disk}

        common.DeLog.objects.create(**data)  # 建立日誌

    super(MachineExDiskAdmin, self).save_model(request, obj, form, change)

  同樣的,還有delete_model:

1

2

3

4

5

6

7

8

9

10

def delete_model(self, request, obj):

    machine.Device.objects.filter(pk=obj.pk).update(device_status='待報廢')

    data = {'server_code': obj.machine,

            'device_type''硬碟',

            'original_code': obj.disk,

            'way''刪除',

            'current_code': '',

            'user_name': request.user}

    common.DeLog.objects.create(**data)  # 建立日誌

    super(MachineExDiskAdmin, self).delete_model(request, obj)

  

6. 修改模版 chang_form.html 讓普通使用者 無法看到 “歷史” 按鈕。

預設 普通使用者下 是存在 “歷史” 按鈕的:

此時  chang_form.html  的程式碼為:

我們將程式碼修改為:

這樣,就可以限制 只讓管理員看到歷史 按鈕了。普通使用者看不到了:

 

7.對單條資料 顯示樣式的修改

 需求如下:

每條資料都有 個確認標識(上圖紅框中),如果已經確認,使用者再點選進入檢視資訊的時候全部只讀顯示,即不能在做修改,如果沒確認在可以修改。如下:

已確認:

未確認:

 

 實現方法:

change_view 方法 和 get_readonly_fields 方法 配合,程式碼:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

def get_readonly_fields(self, request, obj=None):

    """  重新定義此函式,限制普通使用者所能修改的欄位  """

    if request.user.is_superuser:

        self.readonly_fields = ['commit_date''paper_num']

    elif hasattr(obj, 'is_sure'):

        if obj.is_sure:

            self.readonly_fields = ('project_name''to_mail''data_selected''frequency''start_date',

                                    'end_date')

    else:

        self.readonly_fields = ('paper_num''is_sure''proposer''sql''commit_date')

 

    return self.readonly_fields

 

def change_view(self, request, object_id, form_url='', extra_context=None):

    change_obj = DataPaperStore.objects.filter(pk=object_id)

    self.get_readonly_fields(request, obj=change_obj)

    return super(DataPaperStoreAdmin, self).change_view(request, object_id, form_url, extra_context=extra_context)

  注:

change_view方法,允許您在渲染之前輕鬆自定義響應資料。(凡是對單條資料操作的定製,都可以通過這個方法配合實現)
詳細資訊可見:https://docs.djangoproject.com/en/1.10/ref/contrib/admin/#django.contrib.admin.ModelAdmin.change_view

8.修改app的顯示名稱

Dajngo在Admin後臺預設顯示的應用的名稱為建立app時的名稱。

我們如何修改這個app的名稱達到定製的要求呢,其實Django已經在文件裡進行了說明。

從Django1.7以後不再使用app_label,修改app相關需要使用AppConfig。我們只需要在應用的__init__.py裡面進行修改即可:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

from django.apps import AppConfig

import os

 

 

default_app_config = 'hys_operation.PrimaryBlogConfig'

 

VERBOSE_APP_NAME = u"1-本地伺服器資源"

 

 

def get_current_app_name(_file):

    return os.path.split(os.path.dirname(_file))[-1]

 

 

class PrimaryBlogConfig(AppConfig):

    name = get_current_app_name(__file__)

    verbose_name = VERBOSE_APP_NAME

  

 9.自定義列表欄位

上面的一對多和多對多可以資料編輯中顯示,但在列表中沒有顯示。有時還需要顯示一些其他東西。例如兩個欄位相乘計算結果等等。這些都可以通過自定義列表欄位處理和顯示。

例如,兩個模型Blog和Tag。多對多關係。簡單模型程式碼如下:

1

2

3

4

5

6

class Tag(models.Model):

    tag_name = models.CharField(max_length=20,blank=True)

     

class Blog(models.Model):

    caption = models.CharField(max_length=20,blank=True)

    tags = models.ManyToManyField(Tag,blank=True)

   

在Blog模型中有tags欄位,但admin列表顯示不能直接用該欄位,也顯示不出來。可以通過自定義列表欄位顯示。如下設定admin:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

#coding:utf-8

from django.contrib import admin

from blog.models import Blog, Tag

  

# Blog模型的管理器

@admin.register(Blog)

class BlogAdmin(admin.ModelAdmin):

    # listdisplay新增 tags_list 不存在的欄位名

    list_display = ('id''caption''tags_list')

     

    # 定義tags_list,方法名和tags_list一致

    def tags_list(self, blog):

        """自定義列表欄位"""

        tag_names = map(lambda x: x.tag_name, blog.tags.all())

        return ', '.join(tag_names)

   

通過自定義列表欄位,獲取相關資料再列表中顯示,效果如下:

 

參考了部落格:http://yshblog.com/blog/

 

參考網站: http://code.ziqiangxuetang.com/django/django-admin.html

                  http://django-intro-zh.readthedocs.io/zh_CN/latest/part2/

       http://python.usyiyi.cn/translate/django_182/ref/contrib/admin/index.html

                 https://www.ibm.com/developerworks/cn/opensource/os-django-admin/

      http://www.cnblogs.com/linxiyue/p/4074141.html