You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Django-Oscar中添加多类自定义产品?

在Django-Oscar中实现DVD和Book子类产品的方案

嘿,我来帮你搞定这个需求!其实核心就是利用Oscar提供的AbstractProduct抽象基类,结合Django的多表继承来给不同产品类型做子类化,这样DVD和Book既能共享基础产品的所有字段(比如名称、价格、库存),又能各自存储专属的字段。具体步骤我给你拆解清楚:

第一步:替换默认的Product模型

Oscar默认的Product模型是基于AbstractProduct的,但我们需要先在自己的app里定义一个继承自它的基础Product模型,这样后续的DVD和Book才能基于这个自定义模型来扩展:

# 你的app下的models.py
from oscar.apps.catalogue.abstract_models import AbstractProduct
from django.db import models

class Product(AbstractProduct):
    # 这里可以加所有产品通用的额外字段,如果暂时不需要就留空
    pass

# 别忘了导入Oscar的模型补全代码,这步很重要!
from oscar.apps.catalogue.models import *  # noqa

然后去settings.py里把Oscar默认的catalogue app替换成你自己的:

INSTALLED_APPS = [
    # ... 其他已有的app
    '你的app名称.apps.CatalogueConfig',  # 替换成你自己的catalogue配置类
    'oscar.apps.catalogue',
    # ... 其他Oscar相关的app
]

第二步:创建DVD和Book子类模型

接下来就可以用Django的多表继承来创建这两个子类了,它们都继承自我们刚才定义的Product模型,这样自动会关联基础产品表,同时生成各自的表来存专属字段:

# 接着上面的models.py代码继续写
class DVD(Product):
    director = models.CharField(max_length=255, verbose_name="导演")
    length = models.PositiveIntegerField(verbose_name="时长(分钟)")

    class Meta:
        verbose_name = "DVD产品"
        verbose_name_plural = "DVD产品"

class Book(Product):
    author = models.CharField(max_length=255, verbose_name="作者")
    pages = models.PositiveIntegerField(verbose_name="页数")

    class Meta:
        verbose_name = "图书产品"
        verbose_name_plural = "图书产品"

第三步:生成并执行数据库迁移

写完模型后,跑一下Django的迁移命令,让数据库创建对应的表:

python manage.py makemigrations
python manage.py migrate

第四步:配置后台管理(可选)

如果想在Django admin里方便管理这些子类产品,可以把它们注册到admin,并且自定义表单显示专属字段:

# 你的app下的admin.py
from django.contrib import admin
from oscar.apps.catalogue.admin import ProductAdmin
from .models import DVD, Book

class DVDAdmin(ProductAdmin):
    # 把DVD的专属字段加到admin表单里
    fieldsets = ProductAdmin.fieldsets + (
        ("DVD专属信息", {
            'fields': ('director', 'length')
        }),
    )

class BookAdmin(ProductAdmin):
    fieldsets = ProductAdmin.fieldsets + (
        ("图书专属信息", {
            'fields': ('author', 'pages')
        }),
    )

admin.site.register(DVD, DVDAdmin)
admin.site.register(Book, BookAdmin)

一些关键提示

  • 这种多表继承的方式,每个子类会有自己独立的数据库表,通过product_ptr_id外键关联到基础Product表,完美实现“共享基础字段+专属字段独立存储”的需求。
  • 在业务代码里区分产品类型也很简单,比如:
    from .models import DVD
    product = Product.objects.get(id=1)
    if isinstance(product, DVD):
        print(f"这个DVD的导演是:{product.director}")
    

内容的提问来源于stack exchange,提问作者decapo

火山引擎 最新活动