Как показать категории товаров на главной странице?
Я хочу показать все мои продукты ряд за рядом на главной странице по категориям. Предположим, перед началом нового ряда будет заголовок (название категории), затем будут показаны все продукты в соответствии с категорией продукта, а затем снова будет начинаться новый ряд с заголовком в соответствии с категорией. Как я могу это сделать? Я применил 3/4 методов, но ничего не получилось. Ниже я показал один из методов. Он не работает должным образом. Пожалуйста, помогите мне.
views.py:
def home(request):
all_products = Products.objects.all()
context ={
"all_products":all_products,
}
return render(request,'home.html', context)
model.py:
class Category(models.Model):
title = models.CharField(blank=True, null=True, max_length = 100)
def __str__(self):
return str(self.title)
class Products(models.Model):
product_image = models.ImageField(blank=True, null=True, upload_to = "1_products_img")
product_title = models.CharField(blank=True, null=True, max_length = 250)
product_price = models.IntegerField(blank=True, null=True)
offer_price = models.IntegerField(blank=True, null=True)
created_date = models.DateTimeField(blank=True, null=True, auto_now=True)
product_category = models.ForeignKey(Category, related_name="categoty_related_name", on_delete=models.CASCADE, blank=True, null=True)
context_processors.py:
from .models import Category
def categories(request):
return {"categories":Category.objects.all()}
Шаблон:
{% for products in all_products %}
<h4 class="text-start montserrat_alternates_font ">{{products.product_category}}</h4>
<hr>
<!--- product card --->
<div class="col mb-5">
<div class="card h-100">
<!-- Sale badge-->
{% if products.offer_price != None %}
<div class="badge bg-dark text-white position-absolute" style="top: 0.5rem; right: 0.5rem">
SALE
</div>
{% endif %}
<!-- Product image-->
<img class="card-img-top" style="height:150px;" src="{{products.product_image.url}}" alt="..." />
<!-- Product details-->
<div class="card-body ">
<div class="text-center">
<!-- Product name-->
<h5 class="fw-bolder product_title" style="">{{products.product_title}}</h5>
</div>
</div>
</div>
</div>
{% endfor %}
Вам нужно немного изменить свое мышление :)
Самый простой подход - думать от больших "предметов" (как ваш Category
) к меньшим (Product
).
Прежде всего, используйте единственное число для именования моделей, например Product
(без 's', так же как вы сделали с Category
), потому что в противном случае вы получите путаницу в настройках. Кроме того, не называйте поля именем модели, если это действительно необходимо, product_category
должно быть просто category
и так далее.
Во-вторых, откройте большой цикл for
с Category
, который вы передаете как контекст классического представления:
def home(request):
categories = Category.objects.all()
context = {
"categories": categories,
}
return render(request,'home.html', context)
Затем посмотрите на ваше поле ForeignKey в Product
:
class Products(models.Model):
...
category = models.ForeignKey(Category, related_name="products", ...)
Главное - правильно использовать related name
. В своем шаблоне попробуйте использовать логику, подобную этой (плавное использование related_name
в обратных отношениях):
{% for category in categories %}
{{ category.title }}
{% for product in category.products.all %}
{{ product.title }} - {{ product.price }}
{% endfor %}
{% endfor %}
Если вы не установите related_name
, то он будет доступен с помощью <model_name>_set.all()
, в данном случае product_set.all()
(в шаблонах без скобок, конечно). В любом случае, это будет работать как шарм :)