Krystian Kazimierczak
Krystian Kazimierczak

Reputation: 582

Django Categories with subcategories

I was able to show categories for Category Model (Man and Woman). Now I want to make forwarding for a category to the site with subcategory where will show subcategory with product

This is my models.py

class Category(models.Model):
    name = models.CharField(max_length=200,
                            db_index=True)
    slug = models.SlugField(max_length=200,
                            db_index=True)

    class Meta:
        ordering = ('name',)
        verbose_name = 'category'
        verbose_name_plural = 'categories'

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('shop:product_list_by_category',
                       args=[self.slug])

class SubcategoryMan(models.Model):
    category = models.ForeignKey(Category,
                                 related_name='subcategorymans')
    name = models.CharField(max_length=200,
                            db_index=True)
    slug = models.SlugField(max_length=200,
                            db_index=True)

    def __str__(self):
        return self.name

class ProductMan(models.Model):
    category = models.ForeignKey(SubcategoryMan,
                                 related_name='productsman')
    name = models.CharField(max_length=200,
                            db_index=True)
    slug = models.SlugField(max_length=200,
                            db_index=True)
    image = models.ImageField(upload_to='productsman/%Y/%m/%d',
                              blank=True)
    description = models.TextField(blank=True)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    stock = models.PositiveIntegerField()
    available = models.BooleanField(default=True)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ('name',)
        index_together = (('id', 'slug'),)

    def __str__(self):
        return self.name

This is my views.py file

def product_list(request, category_slug=None):
    category = None
    categories = Category.objects.all()
    products = ProductMan.objects.filter(available=True)
    if category_slug:
        category = get_object_or_404(Category, slug=category_slug)
        products = products.filter(category=category)
    return render(request,
                  'shop/product/list.html',
                  {'category': category,
                   'categories': categories,
                   'products': products})

This is my URL (in app shop)

urlpatterns = [
    url(r'^$', views.product_list, name='product_list'),
    url(r'^(?P<category_slug>[-\w]+)/$',
        views.product_list,
        name='product_list_by_category')
]

and this is my list.html

{% extends "shop/base.html" %}
{% load static %}

{% block content %}

    <ul>
        <li>
            <a href="{% url 'shop:product_list' %}">Wszystkie</a>
        </li>
        {% for c in categories %}
            <li>
                <a href="{{c.get_absolute_url}}">{{c.name}}</a>
            </li>
        {% endfor %}
    </ul>

{% endblock %}

I know I must create URL and view for detail, and show product but now I want to know what I can do to create forwarding to the subcategory (create views and URL ? )

Upvotes: 2

Views: 7950

Answers (1)

trixn
trixn

Reputation: 16309

I have category Man and Women. I want to when i click on Man forwarding to new site with subcategory ( T-shirt , Shorts etc. )

This is not what happens. Your django application does not actively forward the client somewhere. In fact there is no way the server can send commands to the client. (Okay actually there are ways, but you do not need this in your use case.)

When the client clicks the link you rendered into the previous response a new page will be requested. The information which category was clicked is in the url. Django delegates that request to the correct view depending on the url to render another template. You already defined the url. Now you need a view and a template. The connection between server and client is stateless. That means your django does not know or keep track of which site the client has opened. It just answers to every single request

The django tutorial covers all the code necessary to do exactly this.

A side note: You do not have not split your categories and products into separate models for each gender. You can just create a model Product with a field gender which enables you to filter every "man category" on the content of this field. Like this:

GENDER_CHOICES = (
    ('man', 'man'),
    ('woman', 'woman'),
    ('kids'), 'kids'),   # yeah that's not a gender but you could want to have this
)

class Product(models.Model): 
    category = models.ForeignKey(Category, related_name='product')
    name = models.CharField(max_length=200, db_index=True)

    # all the other product fields

    gender = models.CharField(max_length=30, choices=GENDER_CHOICES)

If want only the man products in your view you could then filter it like this:

man_products = Product.objects.filter(gender='man')

or this:

# get all men's shoes from the database
man_shoes = Product.object.filter(gender='man', category__slug='shoes')

Upvotes: 3

Related Questions