【问题标题】:How can i make good models for categories in django?如何为 django 中的类别制作好的模型?
【发布时间】:2021-11-09 23:00:49
【问题描述】:

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

我的意思是,一个项目可以属于“sushi”之类的类别 -> nameofsushi,或者属于 sushi -> avocado rolls -> 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)

【问题讨论】:

  • 我认为您的解决方案很好。也许this question 是相关的。

标签: python django django-models


【解决方案1】:

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

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

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

或者你如何只获得菜单类别? 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 模型并使用不同的菜单。

【讨论】:

  • 您好,感谢详细的解决方案。是的,我不想要任何复杂的模型,就像你发布的那样,我在 django 和 python 中很新……我已经尝试过你所说的,但是它不起作用,也许我有点困惑。在我拥有的模型中;类别、MenuCat、MenuSubCat 和 MenuItem。在视图中,我有定义并放置上下文。但是当我尝试在模板中渲染模型时没有显示任何内容,我无法理解什么是“_set”是 python 的东西?喜欢__someword?感谢您抽出宝贵时间观看此内容!
  • _set 是 Django 功能,它允许您访问相关对象。由于我看不到您的模型,因此很难仔细检查。但是例如MenuCat,有多个MenuSubCat,你可以通过menu_cat_obj.menusubcat_set.all()来获得它们(在模板中你将使用menu_cat_obj.menusubcat_set.all。见这里:docs.djangoproject.com/en/3.2/topics/db/examples/many_to_many/…
猜你喜欢
  • 2021-06-25
  • 1970-01-01
  • 2019-10-25
  • 2011-08-08
  • 2018-07-06
  • 2015-09-13
  • 2019-03-26
  • 2022-10-23
  • 2018-01-14
相关资源
最近更新 更多