产品折扣行动

有一天,我与我的一位朋友进行了对话,他在工作中使用了 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 文件。在即将到来的示例中,我们将看到如何做到这一点。