feat: replace color field with colors ManyToManyField in items model
All checks were successful
Build and Push Docker Image / build (push) Successful in 26s

- Updated `Item` model to use a ManyToManyField for colors, replacing the old ForeignKey relationship
- Modified templates to handle multiple color swatches in product details
- Updated admin for managing colors with `filter_horizontal`
- Adjusted views to prefetch related `colors` data for items
- Added migration to apply database changes
This commit is contained in:
2026-05-26 00:20:29 +02:00
parent c42d32c76b
commit af129309ab
5 changed files with 48 additions and 15 deletions

View File

@@ -59,7 +59,8 @@ class ItemAdmin(admin.ModelAdmin):
form = ItemAdminForm form = ItemAdminForm
save_as = True save_as = True
list_display = ('name', 'category', 'subcategory', 'price', 'discount_price', 'is_new', 'is_available', 'created_at') list_display = ('name', 'category', 'subcategory', 'price', 'discount_price', 'is_new', 'is_available', 'created_at')
list_filter = ('is_available', 'is_new', 'color', 'category', 'subcategory', 'created_at') list_filter = ('is_available', 'is_new', 'colors', 'category', 'subcategory', 'created_at')
filter_horizontal = ('colors',)
prepopulated_fields = {'slug': ('name',)} prepopulated_fields = {'slug': ('name',)}
inlines = (ItemImageInline,) inlines = (ItemImageInline,)

View File

@@ -0,0 +1,22 @@
# Generated by Django 6.0.5 on 2026-05-25 22:17
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('items', '0004_color_item_discount_price_item_is_new_item_color'),
]
operations = [
migrations.RemoveField(
model_name='item',
name='color',
),
migrations.AddField(
model_name='item',
name='colors',
field=models.ManyToManyField(blank=True, related_name='items', to='items.color', verbose_name='Цвета'),
),
]

View File

@@ -75,12 +75,11 @@ class Item(models.Model):
) )
is_available = models.BooleanField(default=True, verbose_name='В наличии') is_available = models.BooleanField(default=True, verbose_name='В наличии')
is_new = models.BooleanField(default=False, verbose_name='Новинка') is_new = models.BooleanField(default=False, verbose_name='Новинка')
color = models.ForeignKey( colors = models.ManyToManyField(
'Color', 'Color',
on_delete=models.SET_NULL, blank=True,
null=True, blank=True,
related_name='items', related_name='items',
verbose_name='Цвет', verbose_name='Цвета',
) )
created_at = models.DateTimeField(auto_now_add=True, verbose_name='Дата создания') created_at = models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')
updated_at = models.DateTimeField(auto_now=True, verbose_name='Дата обновления') updated_at = models.DateTimeField(auto_now=True, verbose_name='Дата обновления')

View File

@@ -260,8 +260,8 @@ def index(request: HttpRequest, category: str | None = None) -> HttpResponse:
def detail(request: HttpRequest, category: str, slug: str) -> HttpResponse: def detail(request: HttpRequest, category: str, slug: str) -> HttpResponse:
try: try:
item = ( item = (
Item.objects.select_related('category', 'subcategory', 'color') Item.objects.select_related('category', 'subcategory')
.prefetch_related('images') .prefetch_related('images', 'colors')
.get(category__slug=category.lower(), slug=slug) .get(category__slug=category.lower(), slug=slug)
) )
except Item.DoesNotExist: except Item.DoesNotExist:

View File

@@ -56,16 +56,19 @@
</span> </span>
</div> </div>
{% if item.color %} {% with colors=item.colors.all %}
<div class="product-summary__swatches" aria-label="Цвет товара"> {% if colors %}
<div class="product-summary__swatches" aria-label="Цвета товара">
{% for color in colors %}
<span <span
class="product-summary__swatch product-summary__swatch--active" class="product-summary__swatch"
style="background: {{ item.color.hex_code }};" style="background: {{ color.hex_code }};"
title="{{ item.color.name }}" title="{{ color.name }}"
></span> ></span>
<span class="product-summary__color-name">{{ item.color.name }}</span> {% endfor %}
</div> </div>
{% endif %} {% endif %}
{% endwith %}
{% if item.description %} {% if item.description %}
<div class="product-summary__description">{{ item.description|linebreaksbr }}</div> <div class="product-summary__description">{{ item.description|linebreaksbr }}</div>
@@ -101,3 +104,11 @@
{% include "_fragments/footer.html" %} {% include "_fragments/footer.html" %}
{% endblock %} {% endblock %}
{% block add_js %}
<script>
document.addEventListener('DOMContentLoaded', function () {
Fancybox.bind('[data-fancybox="product-gallery"]');
});
</script>
{% endblock %}