iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 11
2
Modern Web

From Django 1.11 to Django 2.1 系列 第 11

Day11 : Models & Admin (2)

今天我們繼續來討論,究竟 Models 與 Admin之間還藏著什麼不可告人的秘密

Day10所提到的,Django 在創建資料庫的時候,實際上背後偷偷地增加的 key = id 的欄位,為了顯示這個id,我們必須創造一個 models 類別的管理者,必須將管理者一併登入進 Admin.py 才行

而你好不容易在 models.py 新增的 VendorAdmin,之後還要去 admin.py 登陸,你可能會覺得有點麻煩,有沒有更方便的做法? 答案是有的! 而且還能一併將原本登入進去的 Vendor 拿掉

方法就是在 VendorAdmin 上方加上 decorator
@admin.register(classname)

@admin.register(Vendor)
class VendorAdmin(admin.ModelAdmin):
    # 這裡我一併將 Vendor 類別 其它的欄位都加進來了
	list_display = ['id', 'vendor_name', 'store_name', 'phone_number', 'address']

不要忘記去 admin.py 將 Vendor 註解掉唷!

from django.contrib import admin

from .models import Vendor, Food, VendorAdmin

# Register your models here.
# admin.site.register(Vendor)   # < 註解
admin.site.register(Food)

完成上述兩事情,再下 python manage.py runserver,它能正常的運作,這方法是不是相對簡單很多 ^ ^

https://ithelp.ithome.com.tw/upload/images/20181011/20111829UTsFjAmJIH.jpg

Python 的 decorator是一個蠻tricky的方法,不過了解操作手法之後,你會發現它的強大! 這裡不說明它的功能,不過推薦一個猴子都看得懂的英文教學 Primer on Python Decorators

同一個管理者可以登入多個類別,但是list_display的設定必須兩個類別都有相同的欄位,因此這裡我們不建議這麼做

上面我們試著將每一個欄位都SHOW出來了,但此刻你不知道是不是也會想 : 如果我的欄位不只這幾個,那一個個填鴨上去,那真的很無聊! 但其實我們可以更聰明的讓Python幫我們填
修改 list_display = field.name for field in Vendor._meta.fields

@admin.register(Vendor)
class VendorAdmin(admin.ModelAdmin):
	list_display = [field.name for field in Vendor._meta.fields]
    # 上下兩者目的相同
    # list_display = ['id', 'vendor_name', 'store_name', 'phone_number', 'address']

此時我們將 Food 也一併透過相同的方式登陸進來

@admin.register(Food)
class FoodAdmin(admin.ModelAdmin):
	list_display = [field.name for field in Food._meta.fields]

並使用Food的資料來做說明,我預先加入了另外兩筆資料進來
https://ithelp.ithome.com.tw/upload/images/20181011/20111829ZEWbyc12Tq.jpg

當資料庫一大的時候,很多資料常常不是我們想要看的,我們可能只想看某一類的資料,像是只想搜尋某種價位的食物,那麼你就需要用到 過濾 list_filter,在Food裡面新增 list_filter,並將要過濾的欄位填入list_filter = ('price_name',)

@admin.register(Food)
class FoodAdmin(admin.ModelAdmin):
	list_display = [field.name for field in Food._meta.fields]
    # 過濾 price_name
	list_filter = ('price_name',)

我現在才意識我取了一個爛名字,到底什麼是price_name xD,應該是 food_price,anyway,大家了解就好

新增完便能夠看到右方多了一個過濾的欄位,此時你便能透過 food_price price_name 進行過濾的動作
https://ithelp.ithome.com.tw/upload/images/20181011/20111829UFGXl3N5qu.jpg

這只是一個簡單的過濾,有時候你想做的不只是這樣子,因為10號剛領薪,你想要犒賞自己,只想要找 >50價位的麵包,但是資料庫顯示的資料可能有 60 65 70... 各種價位的麵包,這時候你便可以自行設定

# 額外 import 這個套件
from django.utils.translation import gettext_lazy as _

# 自行宣告 類別
class Morethanfifty(admin.SimpleListFilter):

	title = _('price')
	parameter_name = 'compareprice' # url最先要接的參數

	def lookups(self, request, model_admin):
		return (
			('>50',_('>50')), # 前方對應下方'>50'(也就是url的request),第二個對應到admin顯示的文字
			('<=50',_('<=50')),
		)
    # 定義查詢時的過濾條件
	def queryset(self, request, queryset):
		if self.value() == '>50':
			return queryset.filter(price_name__gt=50)
		if self.value() == '<=50':
			return queryset.filter(price_name__lte=50)
            
@admin.register(Food)
class FoodAdmin(admin.ModelAdmin):
	list_display = [field.name for field in Food._meta.fields]
    # 將 Morethanfifty 填入
	list_filter = (Morethanfifty,)

我們選擇了 >50 的選項,此時只會顯示>50的食物,我們就能夠好好犒賞一下自己了 ^^
https://ithelp.ithome.com.tw/upload/images/20181011/20111829HCS99RofN1.jpg

選擇了 >50 會顯示的 url為 http://127.0.0.1:8000/admin/vendor/food/?compareprice=>50
前方的 compareprice 就是對應到我上面所說的 parameter_name,而 >50 則是我們定義的其中一個選項

是不是很簡單(X
除了使用Django內建的 list_filter,你也可以自行設定區間範圍

今天差不多就先講到這裡,自定義過濾的部分若是有不懂的地方也歡迎留言,不過我相信大家應該都沒麼問題

model 跟 admin 實在有太多東西可以玩拉 (哈哈


上一篇
Day10 : Models & Admin (1)
下一篇
Day12 : Models & Admin (3)
系列文
From Django 1.11 to Django 2.1 30

尚未有邦友留言

立即登入留言