在 Django 模型中存储项目类别和子类别的最佳方式

Best way to store category and subcategories of an item in Django models

我想存储像苹果这样的东西,它会被存储为 "Tree Fruit - Apple - Fuji - Organic",而有些物品会有更多类别,比如小麦,它是 "Cereal Grain - Wheat - Soft White Winter - Stephens - Organic"。

class Item(models.Model):

    user = models.ForeignKey(User)
    type = models.CharField(max_length=100, default=None ,blank=True) #Cereal Grain
    commodity = models.CharField(max_length=100, default=None ,blank=True) #Wheat
    cl = models.CharField(max_length=100, default=None ,blank=True) #Soft White Winter
    variety = models.CharField(max_length=100, default=None ,blank=True) #Stephens
    market = models.CharField(max_length=100, default=None ,blank=True) #Organic

    def __str__(self):
        return u"%s" % (self.user)



class Shorten_Item(models.Model):

    user = models.ForeignKey(User)
    type = models.CharField(max_length=100, default=None ,blank=True) #Tree Fruit
    commodity = models.CharField(max_length=100, default=None ,blank=True) #Apple
    variety = models.CharField(max_length=100, default=None ,blank=True) #Fuji
    market = models.CharField(max_length=100, default=None ,blank=True) #Organic


    def __str__(self):
        return u"%s" % (self.user)

将有与那些 table 相关联的成本项目参考。

class User_Variable_Items(models.Model):

    #variety = models.ForeignKey(User_Variety)
    category = models.CharField(max_length=100,default=None ,blank=True)
    sub_category = models.CharField(max_length=100,default=None ,blank=True)
    item = models.CharField(max_length=100,default=None ,blank=True)
    price = models.DecimalField(max_digits=20,decimal_places=2,default=None ,blank=True)
    unit = models.CharField(max_length=100,default=None ,blank=True)
    quantity = models.FloatField(default=0,blank=True)
    total = models.DecimalField(max_digits=20,decimal_places=2,default=None ,blank=True)

    class Meta:
        verbose_name_plural = _("User_Variable_Items")

class User_Fixed_Items(models.Model):

    #variety = models.ForeignKey(User_Variety)
    category = models.CharField(max_length=100,default=None ,blank=True)
    price = models.DecimalField(max_digits=20,decimal_places=2,default=None ,blank=True)
    unit = models.CharField(max_length=100,default=None ,blank=True)
    quantity = models.FloatField(default=0,blank=True)
    total = models.DecimalField(max_digits=20,decimal_places=2,default=None ,blank=True)

    class Meta:
        verbose_name_plural = _("User_Fixed_Items")

User_Variable_Cost_ItemsUser_Fixed_Cost_items 引用上面的 table 之一(而不是两者)的最佳方法是什么?

谢谢

如果可以重组模型,则可以使用模型继承(https://docs.djangoproject.com/en/1.8/topics/db/models/#model-inheritance)

您的 Item 模型可能是 Shorten_Item 的子 class,因为它只包含一个额外的字段,即 cl = CharField()

您可以保持 Shorten_Item 不变,然后让 Item 从该模型继承:

class Item(Shorten_Item):
    cl = models.CharField(max_length=100, default=None ,blank=True)

现在在你的另一个 class,

class User_Variable_Items(models.Model):

    ...
    # Add a foreign key to the base Item class
    # Which by inheritance can contain both keys from Shorten_Item and Item
    item = ForeignKey('Shorten_Item')

当您检索 Shorten_Item 的 ID 时,使用您的业务逻辑来确定是否要将其用作 Shorten_ItemItem(通过将其向下转换为 Item 需要时)

如果您不能重组您的模型以从继承中获益,您唯一的解决方案可能是使用 item_id = IntegerField() 作为 "foreign key",它将能够指向任何 table,并且您必须自己编写更多查询

我想你想做的是:

拥有来自特定类别的可以在继承层次结构上的项目类型。 Itens 可以有不同的类型和不同的东西,这听起来像一个继承结构(例如 Item > PriceFixedItem 和 Item > VariablePriceItem)。

通过这种方式,您可以尝试编写一个数据结构来存储和恢复数据库中的数据。你能尝试做这样的事情吗:

创建一个引用他自己的模型,制作一个类别树,可以是任何东西:

class Category(models.Model):
     parent = models.ForeignKey('self') # Here category will refer to it self
     name = models.CharField()

现在你的物品只能引用一个类别,你可以把这里的东西变得更动态:

 class Item(models.Model):
     category = models.ForeignKey(Category)
     name = models.CharField()
     price = models.FloatField()

我们现在将拥有不同类型的物品:

class FixedPriceItem(Item):
    pass

class VariablePriceItem(Item):
    price_tax = models.FloatField()

现在最好的就是我们怎么有这个结构,Django可以解决你遇到的问题,但是怎么办?很简单,看这个:

class UserItem(models.Model):
    item = models.ForeignKey(Item)

从现在开始,您可以使用一种对象类型来管理用户项,这非常好维护。我在这里看到的最重要的事情是你试图在数据库结构上解决这个问题,但是当你在像 Django 这样的 ORM 框架上编程时,你不必太关心你的数据库结构,你需要解决您的编程语言问题,Python 在这种情况下,因此使用 OO 概念解决该问题很简单,例如这个。另一件重要的事情是一个你必须终生牢记的概念:拥有数据的对象,就是关心数据的对象。如果你在错误的地方实现你的控制逻辑,你将不得不写更多,哭更多,在这个例子中,你必须让 Item 对象关心它们将呈现,计算或存储他的数据。不要尝试在 User 的 类 上实现控件,当您拥有另一种类型的项目时,这将非常有价值,并且您需要再放一个 if 来验证是否使用此项目,例如这个或那个。