首页 > 解决方案 > 姜戈。类别和子类别

问题描述

我想通过 Django 中的类别和子类别进行导航。

现在我有这个:

127.0.0.1:8000/products/最后一个子类别/product slug

我想做

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

像这样:

我的模型.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])

我的网址.py

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

视图.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)

以及如何显示属于一个类别的所有产品。顺便说一句,如果按该父猫排序,是否可以显示属于一个父类别的所有项目。?例如所有食物

标签: pythondjango

解决方案


听起来您想要完成的是为您的类别和子类别创建一个树结构。有几个工具可以帮助在 Django 中更易于管理。我花了相当多的时间尝试自己按照这些思路实现一些东西,并最终找到了这些工具来节省大量时间和挫败感。

为此目的上升到顶部的两个似乎是Django-mpttDjango-treebeard。两者都非常有用,尽管具有不同的优点和缺点。对我来说,我倾向于使用 Django-mptt,主要是因为我发现文档更全面。

您可以使用 mptt 执行的操作的示例:

模型.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 = 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])

视图.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)

希望您可以通过查看索引视图来了解当您编写模板以显示此信息时,此附加上下文有多方便。这是一个非常简单的例子,但应该提供一些想法。


推荐阅读