我怎样才能为 Django 中的类别制作好的模型?

How can i make good models for categories in django?

我正在尝试制作在线菜单。我想制作一个类别、子类别和属于其中一个的项目。

我的意思是,商品可以属于“寿司”-> nameofsushi 等类别,也可以属于寿司 -> 鳄梨卷 -> nameofsushi 等子类别。

我的 models.py 中有类似的东西,但有更好的方法吗?

class Category(models.Model):
    name = models.CharField(max_length=200)
    description = models.TextField(max_length=500, verbose_name='Descripción', blank=True, null=True)
    parent = models.ForeignKey('self', related_name='children', null=True, blank=True, on_delete=models.CASCADE)
    
    def __str__(self):
        return 'Category: {}'.format(self.name)

class MenuItem(models.Model):
    name = models.CharField(max_length=200)
    image = models.ImageField(upload_to='menu_images/', null=True, blank=True)
    description = models.TextField(blank=True, null=True)
    price = models.DecimalField(max_digits=6, decimal_places=0)
    other_Price = models.DecimalField(max_digits=6, decimal_places=0, null=True, blank=True)
    categories = models.ManyToManyField('Category', related_name='item', null=True, blank=True)
    
    def __str__(self):
        return 'MenuItem: {}'.format(self.name)

您需要仔细考虑您的模型设计。您设计类别的方式允许您拥有无限的子类别。你真的需要这种灵活性吗?因为它是以复杂性为代价的。想想你将如何与模型互动。

对于您当前的设计,如果不使用一些粗糙的递归在 Python 中对其进行预处理,则在 Django 模板中呈现将具有挑战性,因为您无法先验地知道您有多少嵌套子类别。您可以有子类别、子子类别、子子类别等等。

此外,查询您的模型会很复杂。假设您有 'Cat1'->'Sub-cat1'->'Sub-sub-cat1'->'menuitem1'。您如何找到属于 'sub-cat1' 的所有菜单项?我能想到的就是MenuItem.objects.filter(parent__parent=subcat1_obj)。不是很 Pythonic 也不是很清楚 reader。而你 运行 遇到了问题,因为你不知道你有多少层子类别。

或者如何只获取菜单类别? Category.objects.filter(parent=None)。从这段代码中我们正在谈论的内容并不明显。

如果您的用例允许,我会以这种方式简化您的模型设计:

class MenuCategory(models.Model):
    category = models.ForeignKey(Category, ...)
    ...

class MenuSubCategory(models.Model):
    menu_category = models.ForeignKey(MenuCategory, ...)
    ...

class MenuItem(models.Model):
    menu_categories = models.ManyToManyField(MenuCategory, ...)
    menu_subcategories = models.ManyToManyField(MenuSubCategory, ...)
    ...

现在在模板中渲染您的模型会很简单(给定 context['menu_categories'] = MenuCategory.objects.all()):

{% for cat in menu_categories %}
  {% for item in cat.menuitem_set.all %}
    {{ item }}
  {% endfor %}
  {% for subcat in cat.menusubcategory_set.all %}
    {% for item in subcat.menuitem_set.all %}
      {{ item }}
    {% endfor %}
  {% endfor %}
{% endfor %}

现在查询你的模型也会更加清晰。如果需要,您还可以添加 Menu 模型并具有不同的菜单。