Django. Категории и подкатегории - PullRequest
1 голос
/ 07 февраля 2020

Я хочу сделать навигацию по категориям и подкатегориям в Django.

Теперь у меня есть это:

127.0.0.1: 8000 / products / last subcategory / product slug

и я хочу сделать

127.0.0.1: 8000 / products / category / subcategory / subsubcategory /.../ product slug

что-то вроде этого:

  • Еда
    • Овощи
      • Морковь
      • Брокколи
      • Помидоры
    • Фрукты
      • Яблоко
      • Груша
  • Напитки

my models.py:

class Product(models.Model):
    title       = models.CharField(max_length=120)
    slug        = models.SlugField(unique=True)
    category    = models.ForeignKey('Category', on_delete=models.CASCADE) 
    description = models.TextField(blank=True,null=True)

    def save(self, *args, **kwargs):
        self.slug = slugify(self.title)
        super(Product,self).save(*args, **kwargs)

    def get_absolute_url(self):
        return self.slug

class Category(models.Model):
    name = models.CharField(max_length=200)
    slug = models.SlugField(unique=True)
    parent = models.ForeignKey('self',blank=True, null=True         ,related_name='child', on_delete=models.CASCADE)
    class Meta:
        unique_together = ('slug', 'parent',)    
        verbose_name_plural = "categories"   

    def __str__(self):                           
        full_path = [self.name]            
        k = self.parent
        while k is not None:
            full_path.append(k.name)
            k = k.parent

        return ' -> '.join(full_path[::-1])

my urls.py

path('', ProductList, name='product-list1'),
path('<category_slug>/', products_by_category, name='product-categories'),

views.py

def ProductList(request):
    products = Product.objects.all()
    products = products.order_by('-publish')
    categories = Category.objects.filter(parent__isnull=True)
    context = {
        'products':products,
        'categories':categories,
    }
    template = 'products/product_list.html'
    return render(request, template ,context)


def products_by_category(request,category_slug):
    products = Product.objects.all()
    categories = Category.objects.filter(parent__isnull=True)
    slug = category_slug
    if slug:
        category_s = get_object_or_404(Category,slug = slug)    
        products = products.filter(category = category_s)
    context = {
        'products':products,
        'categories':categories,
        'category':category_s,
        'page_obj':page_obj,
    }
    template = 'products/products_by_category_list.html'
    return render(request,template,context)

И как я могу отобразить все товары одной категории. Кстати, можно ли показать все элементы, которые принадлежат к одной родительской категории, если сортировать по этой родительской категории? Например, вся пища

  • Еда
    • Овощи
      • Морковь
      • Брокколи
      • Помидоры
    • Фрукты
      • Яблоко
      • Груша
  • Напитки

1 Ответ

0 голосов
/ 21 марта 2020

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

Похоже, что два, которые поднимаются на вершину для этой цели, Django -mptt и Django -treebeard . Оба весьма полезны, хотя и с разными сильными и слабыми сторонами. Для меня я обычно предпочитал работать с Django -mptt, потому что я нашел документацию более тщательной.

Пример того, что вы можете сделать с помощью mptt:

models.py

...

from mptt.models import MPTTModel, TreeForeignKey

class Product(models.Model):
    title       = models.CharField(max_length=120)
    slug        = models.SlugField(unique=True)
    description = models.TextField(blank=True,null=True)
    category    = models.ForeignKey(
        'Category',
        related_name="products",
        on_delete=models.CASCADE
    ) 

    def save(self, *args, **kwargs):
        self.slug = slugify(self.title)
        super(Product,self).save(*args, **kwargs)

    def get_absolute_url(self):
        return self.slug

class Category(MPTTModel):
    name = models.CharField(max_length=200)
    slug = models.SlugField(unique=True)
    parent = models.TreeForeignKey(
        'self',
        blank=True,
        null=True,
        related_name='child',
        on_delete=models.CASCADE
    )

    class Meta:
        unique_together = ('slug', 'parent',)    
        verbose_name_plural = "categories"   

    def __str__(self):                           
        full_path = [self.name]            
        k = self.parent
        while k is not None:
            full_path.append(k.name)
            k = k.parent

        return ' -> '.join(full_path[::-1])

views.py

...

def index(request):
    if request.method == 'GET':
        category_id = int(request.GET.get('category_id', default=1))
        current_category = Category.objects.get(pk=category_id)

        children = current_category.get_children()
        ancestors = current_category.get_ancestors()
        products = current_category.products.all()

        context = {
            'categories': children,
            'current_category': current_category,
            'ancestors': ancestors,
            'products': products,
        }

    return render(request, 'your_site/index.html', context)

Надеемся, что, посмотрев на индексное представление, вы сможете понять, насколько удобен этот дополнительный контекст, когда вы пишете шаблон для отображения этой информации. Это очень простой пример, но он должен дать некоторые идеи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...