How to get Category from Product? Django

Question:

I’m trying to create a search bar where user can choose Category and write product name. So I can display all products in that category where the name of product matches with what he wrote in text input.

So I have Category -> Subcategory -> Product. Is there any way to get Category object from Product model? (I don’t have field for category in product model)

Here is my models.py file:

# models.py

class Category(models.Model):
    name = models.CharField(max_length=100, null=True, blank=True)
    created = models.DateTimeField(auto_now_add=True)
    class Meta:
        verbose_name_plural = 'Categories'
    def __str__(self):
        return self.name
    
class Subcategory(models.Model):
    category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, related_name='subcategories')
    name = models.CharField(max_length=200, null=True, blank=True)
    created = models.DateTimeField(auto_now_add=True)
    top5 = models.BooleanField(default=False, null=True, blank=True)
    featured = models.BooleanField(default=False, null=True, blank=True)
    class Meta:
        verbose_name_plural = 'Subcategories'
    def __str__(self):
        return self.name

class Product(models.Model):
    name = models.CharField(max_length=200, null=True, blank=True)
    subcategory = models.ForeignKey(Subcategory, on_delete=models.SET_NULL, null=True, related_name='products')
    image = models.ImageField(null=True, blank=True, upload_to='products/')
    price_old = models.DecimalField(decimal_places=2, max_digits=7, null=True, blank=True)
    price_new = models.DecimalField(decimal_places=2, max_digits=7, null=True, blank=True)
    description = models.TextField()
    created = models.DateTimeField(auto_now_add=True)
    def __str__(self):
        return self.name

    # @property
    # def category(self):
    #     return self.subcategory.category

Here as you can see I tried to create a property to get the category, but now I’m struggling to filter products that share the same category

Here is my views.py file:

def search_products(request):
    q = request.GET.get('q') if request.GET.get('q') != None else ''
    category = Category.objects.get(name=request.GET['category'])
    products = Product.objects.filter(name__icontains=q, category=category) <-- This line

    context = {'products':products, 'q':q}
    return render(request, 'search_products.html', context)

If you have any ideas, I would be really glad to hear you!

Asked By: Timur Arazmedov

||

Answers:

Yes. Since your Product model have a foreign key to Subcategory, and Subcategory has a foreign key to Category, you can do the following in your template:

{% for product in products %}
 Category: {{ product.subcategory.category }}
 Product: {{ product }}</div>
{% endfor %}

To filter them, you should use the double underscore (__) syntax:

products = Product.objects.filter(
    name__icontains=q, 
    subcategory__category=category
)
Answered By: Selcuk
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.