Как сделать хорошие модели для категорий в 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)

Вам необходимо тщательно продумать дизайн вашей модели. То, как вы разработали категории, позволяет вам иметь неограниченное количество подкатегорий. Действительно ли вам нужна такая гибкость? Ведь за нее приходится платить сложностью. Подумайте о том, как вы будете взаимодействовать с моделями.

При вашем текущем дизайне было бы сложно сделать рендеринг в шаблоне Django без предварительной обработки в Python, используя какую-то ужасную рекурсию, потому что у вас нет возможности apriori узнать, сколько вложенных подкатегорий у вас есть. У вас может быть подкатегория, подсубкатегория, подсубкатегория и так далее.

Кроме того, запросы к вашим моделям будут сложными. Допустим, у вас есть 'Cat1'->'Sub-cat1'->'Sub-sub-cat1'->'menuitem1'. Как найти все пункты меню, которые являются потомками 'sub-cat1'? Все, что я могу придумать, это MenuItem.objects.filter(parent__parent=subcat1_obj). Не очень питонично и непонятно для читателя. И вы сталкиваетесь с проблемами, поскольку не знаете, сколько уровней подкатегорий у вас есть.

Или как получить только категории меню? 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 и иметь различные меню.

Вернуться на верх