在 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_Items
和 User_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_Item
或 Item
(通过将其向下转换为 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
来验证是否使用此项目,例如这个或那个。
我想存储像苹果这样的东西,它会被存储为 "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_Items
和 User_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_Item
或 Item
(通过将其向下转换为 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
来验证是否使用此项目,例如这个或那个。