產品折扣行動

有一天,我與我的一位朋友進行了對話,他在工作中使用了 Laravel PHP 框架。當我告訴他 Django 有自己的全包式 HTML CRUD 系統時,為了與資料庫互動,稱為 Django admin ,他的眼睛突然出現了! 他告訴我:“ 我花了幾個月的時間為我當前的網路應用程式構建一個 Admin 介面,而你說你擁有所有這些,而無需編寫一行程式碼? ”。我回答“ Yeap!

Django 管理是一個強大的功能的 Django 提供很多東西。其中一個是行動

但是什麼行動是什麼?

假設你有一個模型,並且你已經新增了一些條目(可能數百個,也許數千個)。現在,你希望在使用控制檯(python manage.py shell)的情況下將規則操作應用於其中至少一個 :

# python manage.py shell (interactive console)

from math import ceil

from my_app.models import Product

DISCOUNT = 10  # percentage

for product in Product.objects.filter(is_active=True):
    """ Set discount to ALL products that are flagged as active """
    multiplier = DISCOUNT / 100.  # DISCOUNT / 100 in python 3 (without dot)
    old_price = product.price
    new_price = ceil(old_price - (old_price * multiplier))  # seller wins :)
    product.price = new_price
    product.save(update_fields=['price'])

你是否注意到我們將折扣應用於所有產品。如果我們想將這個邏輯應用於特定的邏輯怎麼辦?或者,如果我們想手動輸入折扣值,然後將此值應用於某些產品?所有這些都通過 Django 管理員! 你走在正確的軌道上。Django 行動 FTW。讓我們看一個完整的例子。

基礎:

  • Python 3.4.3
  • Django 1.10
  • SQLite(內建 Python,無需額外的安裝設定)

該模型:

  • 代表我們的電子商店的產品
  • 產品的價格是整數(不是小數)

目標:

  • 能夠通過 Django Admin 介面對一個或多個產品條目應用固定折扣。

設定(app,model 和 Django admin)

假設你已經啟動了一個專案 ,請轉到 manage.py 所在的目錄並建立一個名為 stock 的應用程式,方法是輸入:

python manage.py createapp stock

Django 會自動為你建立一個目錄結構。去編輯 models.py 檔案並新增:

# models.py

from django.db import models

class Product(models.Model):
    name = models.CharField('Product name', max_length=100)  # required field
    price = models.PositiveIntegerField('Product price')

    def __str__(self):  # __unicode__ in Python 2
        return self.name

我們的 Product 模型已經建立,但資料庫中還沒有。為了使遷移工作,我們的應用程式必須包含在 INSTALLED_APPS 列表中。

編輯你的 settings.py 檔案並在 INSTALLED_APPS 列表下新增:

# settings.py

INSTALLED_APPS = [
    # ... previous Django apps
    'stock.apps.StockConfig',
]

現在執行:

python manage.py makemigrations
python manage.py migrate

migrate 命令之後,你的資料庫現在有一個名為 product 的表,其中包含三列 idnameprice。到現在為止還挺好!

如果你沒有更改 ROOT_URLCONF 檔案中的任何內容( 通常位於資料夾 <your_project_name>/<your_project_name>/中),則指向 Django 管理站點的 URL 應為:

# urls.py

urlpatterns = [
    # ... other URLs
    url(r'^admin/', admin.site.urls),
]

到目前為止,我們還沒有看到有關 Django 管理操作的任何具體內容。最後一步,在 stock/admin.py 檔案中新增:

# admin.py

from django.contrib import admin

from .models import Product

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    pass

好。設定完成。只是為了確保一切正常,執行:

python manage.py runserver

並使用你最喜歡的瀏覽器訪問頁面 127.0.0.1:8000/admin/。你應該看到閃亮光鮮,了不起 Django 管理頁面,它允許你 ç reate- [R ead- U pdate- d elete 你 Product 典範! 如果有任何機會,上面的頁面會詢問你的使用者名稱/密碼而你沒有任何問題。你還沒有建立一個 User 來登入管理員。只需執行:

python manage.py createsuperuser

輸入你的姓名,電子郵件,使用者名稱和密碼(兩次),你就完成了。

生成一些假冒產品

到目前為止,我們已經建立了模型但沒有條目(沒有產品)。我們需要一些條目來闡明 Django 管理員行動的力量。

我們將創造 100 種產品並與之合作。但是,我們不會手動按下 ADD 按鈕並輸入 nameprice,而是編寫一個指令碼來為我們完成工作。

執行 python manage.py shell 並輸入以下內容:

# python manage.py shell

from stock.models import Product    

for i in range(1, 101):
    p = Product.objects.create(name='Product %s' % i, price=i)

上面的 for 迴圈建立(這意味著資料儲存在資料庫中)100 個產品(條目)名稱為 Product 1Product 2,… Product 100 和價格 12,…,100

要通過 Django 管理頁面檢視這些產品,請再次訪問 127.0.0.1:8000/admin/並單擊 Products 連結:

StackOverflow 文件

享受你自動生成的 100 種產品:

StackOverflow 文件

這被稱為 Django 的 change list 頁面。現在,為了讓它看起來更漂亮,編輯你的 stock/admin.py 檔案並輸入:

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    list_display = ('name', 'price')

現在,點選重新整理,你應該會看到顯示價格的第二列。

唷! 最後的行動

回顧一下,我們有模型,我們有條目。接下來,我們要建立一個操作,一旦選擇它將對所選產品進行 30%的折扣。

你是否注意到 change list 頁面頂部有一個選擇框,標籤為 Action?Django 會自動在每個執行 D elete 操作的條目上新增預設操作。

Django 管理操作是作為簡單函式編寫的。讓我們潛入。編輯 stock/admin.py 檔案並新增以下內容:

# admin.py

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    list_display = ('name', 'price')
    actions = ['discount_30']

    def discount_30(self, request, queryset):
        from math import ceil
        discount = 30  # percentage

        for product in queryset:
            """ Set a discount of 30% to selected products """
            multiplier = discount / 100.  # discount / 100 in python 3
            old_price = product.price
            new_price = ceil(old_price - (old_price * multiplier))
            product.price = new_price
            product.save(update_fields=['price'])
    discount_30.short_description = 'Set 30%% discount'

這裡有幾點需要注意:

  • ProductAdmin 類有一個額外的屬性(actions),它是一個字串列表(每個字串是代表該動作的函式的名稱)。
  • 動作功能是 ProductAdmin 類的一種方法。它以 ModelAdmin 例項(self,因為這是一種方法),HTTP request 物件和 queryset(所選物件 - 條目 - 產品的列表)為引數。
  • 最後一行是一個函式屬性(short_description),它在 actions 選擇框中設定顯示的名稱(為了轉義單個%,有一個 double%)。

在函式操作中,我們迭代每個產品(被選中),我們將其值設定減少 30%。然後我們使用引數 update_fields 呼叫 save() 方法,以強制對資料庫中 update_fields 列表中包含的欄位(而不是模型的所有欄位上的 UPDATE)執行 UPDATE,這是出於效能原因(不是效能)在這個例子中獲得,只有 2 列,但你明白了。)

現在,在 change list 頁面點選重新整理,你應該看到你的行動在 delete 之下。繼續選擇一些產品(使用左上角核取方塊左側的每個或所有產品的核取方塊),選擇 Set 30% discount 操作並單擊 Go 按鈕。而已!

StackOverflow 文件

當然,在大多數情況下這不是很方便,因為此操作不允許你輸入不同的折扣金額。每次要應用其他折扣時,都必須編輯 admin.py 檔案。在即將到來的示例中,我們將看到如何做到這一點。