feat: add item images, product detail page, and gallery support in catalog
All checks were successful
Build and Push Docker Image / build (push) Successful in 45s

- Added `ItemImage` model with migration for image handling and metadata
- Implemented product gallery in `detail.html` with thumbnails for additional images
- Updated `Item` model to include `primary_image` property for gallery logic
- Enhanced `catalog/index.html` to support item thumbnails
- Updated `catalog.css` for responsive gallery and item list styling
- Extended catalog views to prefetch images for efficient queries
- Added comprehensive tests for catalog and detail views
- Configured Django to serve media files in development
- Updated admin with inline support for managing `ItemImage` entities
This commit is contained in:
2026-04-26 21:55:32 +02:00
parent d0651274d6
commit bb321dfa22
15 changed files with 817 additions and 23 deletions

View File

@@ -0,0 +1,69 @@
{% extends "_layouts/base.html" %}
{% load static %}
{% block title %}{{ item.name }}{% endblock %}
{% block add_css %}
<link rel="stylesheet" href="{% static "css/catalog.css" %}">
{% endblock %}
{% block content %}
{% include "_fragments/header.html" with active="catalog" %}
{% url 'detail' item.category.slug item.slug as product_url %}
{% include '_fragments/breadcrumbs.html' with url_1='/' text_1='Главная' url_2='/catalog/' text_2='Каталог' url_3='/catalog/'|add:item.category.slug|add:'/' text_3=item.category.name url_4=product_url text_4=item.name %}
<main class="container product-detail">
<section class="product-gallery" aria-label="Изображения товара">
<div class="product-gallery__main">
{% if primary_image %}
<a href="{{ primary_image.image.url }}" data-fancybox="product-gallery">
<img src="{{ primary_image.image.url }}" alt="{{ primary_image.alt|default:item.name }}">
</a>
{% else %}
<div class="product-gallery__placeholder">Нет фото</div>
{% endif %}
</div>
{% if images %}
<div class="product-gallery__thumbs">
{% for image in images %}
<a class="product-gallery__thumb{% if forloop.first %} active{% endif %}" href="{{ image.image.url }}" data-fancybox="product-gallery">
<img src="{{ image.image.url }}" alt="{{ image.alt|default:item.name }}">
</a>
{% endfor %}
</div>
{% endif %}
</section>
<section class="product-summary" aria-label="Информация о товаре">
<p class="product-summary__category">{{ item.category.name }}</p>
<h1 class="product-summary__title">{{ item.name }}</h1>
<div class="product-summary__meta">
<span class="product-summary__price">{{ item.price }} руб.</span>
<span class="product-summary__availability {% if item.is_available %}available{% else %}unavailable{% endif %}">
{% if item.is_available %}В наличии{% else %}Нет в наличии{% endif %}
</span>
</div>
<div class="product-summary__swatches" aria-hidden="true">
<span class="product-summary__swatch product-summary__swatch--dark"></span>
<span class="product-summary__swatch product-summary__swatch--graphite"></span>
<span class="product-summary__swatch product-summary__swatch--taupe"></span>
<span class="product-summary__swatch product-summary__swatch--sand"></span>
</div>
{% if item.description %}
<div class="product-summary__description">{{ item.description|linebreaksbr }}</div>
{% endif %}
<div class="product-summary__actions">
<button class="product-summary__button product-summary__button--primary" type="button">В корзину</button>
<button class="product-summary__button product-summary__button--secondary" type="button">Купить</button>
</div>
</section>
</main>
{% include "_fragments/footer.html" %}
{% endblock %}