将产品差异逻辑嵌入Django模型中

时间:2013-05-12 19:02:43

标签: django orm python-2.7

我想知道如何根据它的变体部分对我的产品模型进行建模以自动创建(以及admin-App也会理解它)产品的变体。

我的产品有;

  • 颜色
  • 尺寸

并且可能在将来获得更多功能。

如何为Product类建模以生成产品的所有变体?

假设我要创建一个新的颜色产品Red Blue Green和尺寸XS S M L XL

class Product(models.Model):
    name = models.CharField(max_length=200)

class Color(models.Model):
    product = models.ForeignKey(Product)
    name = models.CharField(max_length=200)

class Size(models.Model):
    product = models.ForeignKey(Product)
    name = models.CharField(max_length=200)

class FutureVariant(models.Model):
    product = models.ForeignKey(Product)
    name = models.CharField(max_length=200)

# etc.

现在我需要一种智能方法,当我为该产品自动创建所有颜色大小 - [FUTURE VARIANT]时。

所以我会告诉Django;

  • 创建新产品
    • 使用颜色Red Blue Green
    • 尺寸XS S M L XL

Product class将在products_product表中生成具有所有可能组合的产品。

我几乎可以肯定这有设计缺陷。但我只是好奇如何将这个逻辑放在ORM中,而不是编写奇怪的程序代码,这可能会违反DRY原则。

在数据库逻辑中,我会想到这样的东西;

PRODUCTS
- id
- name

PRODUCTS_VARIANTS_COLORS
- id
- name
- html_code

PRODUCTS_VARIANTS_SIZES
- id
- name

PRODUCTS_VARIANTS_TABLES
- table_name
- table_id

PRODUCTS_VARIANTS
- product_id
- variant_table
- variant_id

这样我可以制作无穷无尽的变体表,只要我在PRODUCTS_VARIANTS_TABLES中注册它们并将它们的名称存储为相关的。 PRODUCTS_VARIANTS将保留产品的所有变体,包括它们的组合。我还希望有一个选择阶段,用户可以选择(在HTML复选框列表中)它所做和不想要的变体。

问题(我认为)这不会真正符合ORM中的逻辑。

2 个答案:

答案 0 :(得分:2)

我不知道您是在询问替代方案还是只是想让自己的方式发挥作用,但是如何将产品从其属性中分离出来呢?

因此,您只需拥有Attribute模型,而不是拥有单独的属性模型。通过这种方式,您可以在未来对数据库进行验证,这样您就可以轻松添加更多属性(例如,如果您的产品具有高度和宽度而不仅仅是颜色或大小)。

class AttributeBase(models.Model):
    label = models.CharField(max_length=255) # e.g. color, size, shape, etc.
    ...

class Attribute(models.Model):
    base = models.ForeignKey('AttributeBase', related_name='attributes')
    value = models.CharField(max_length=255) # e.g. red, L, round, etc.
    internal_value = models.CharField(max_length=255, null=True, blank=True) # other values you may need e.g. #ff0000, etc.
    ...

class ProductAttribute(Attribute):
    product = models.ForeignKey('Product', related_name='attributes')

现在可以很容易地为产品创建所有属性......

class Product(models.Model):
    ...

    def add_all_attributes(self):
        for attribute in Attribute.objects.all():
            self.attributes.add(attribute)

现在当您使用product.add_all_attributes()时,该产品将包含每个属性。你甚至可以让它添加某个AttributeBase

的属性
def add_all_attributes_for_base(self, label):
    base = AttributeBase.objects.get(label=label)
    for attribute in base.attributes.all():
        self.attributes.add(attribute)

答案 1 :(得分:1)

你可以写一些东西:

class Product(models.Model):

    @classmethod
    def create_variants(cls):
        # compute all possible combinations
        combinations = ...
        for combination in combinations:
            Product.objects.create(**combination)

通过注册可能的变体及其可能的值,确实可以创建所有组合。

请注意,ORM可以帮助您将Django对象映射到数据库记录,它不会帮助您生成要保存的数据库记录(读取:Django模型)。