feat: Унификация slug-идентификаторов и улучшение формы комплектов

- Добавлено поле slug в модель Product с автоматической транслитерацией кириллицы
- Обновлена логика генерации slug в Product и ProductKit с использованием unidecode
- Изменена логика обработки изображений: теперь используется slug вместо sku
- Улучшен UX формы создания комплекта: блок загрузки фото доступен сразу при создании

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-23 14:40:53 +03:00
parent 3b50d82d19
commit 9a232c6813
2 changed files with 23 additions and 7 deletions

View File

@@ -322,6 +322,7 @@ class Product(models.Model):
name = models.CharField(max_length=200, verbose_name="Название")
sku = models.CharField(max_length=100, blank=True, null=True, verbose_name="Артикул", db_index=True)
slug = models.SlugField(max_length=200, unique=True, blank=True, verbose_name="URL-идентификатор")
variant_suffix = models.CharField(
max_length=20,
blank=True,
@@ -398,6 +399,20 @@ class Product(models.Model):
if not self.sku:
self.sku = generate_product_sku(self)
# Автоматическая генерация slug из названия с транслитерацией
if not self.slug or self.slug.strip() == '':
from unidecode import unidecode
# Транслитерируем кириллицу в латиницу, затем применяем slugify
transliterated_name = unidecode(self.name)
self.slug = slugify(transliterated_name)
# Убеждаемся, что slug уникален
original_slug = self.slug
counter = 1
while Product.objects.filter(slug=self.slug).exclude(pk=self.pk).exists():
self.slug = f"{original_slug}-{counter}"
counter += 1
# Автоматическая генерация ключевых слов для поиска
# Собираем все релевантные данные в одну строку
keywords_parts = [
@@ -510,7 +525,10 @@ class ProductKit(models.Model):
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.name)
from unidecode import unidecode
# Транслитерируем кириллицу в латиницу, затем применяем slugify
transliterated_name = unidecode(self.name)
self.slug = slugify(transliterated_name)
# Убеждаемся, что slug уникален
original_slug = self.slug
counter = 1
@@ -774,9 +792,9 @@ class ProductPhoto(models.Model):
# Если было загружено новое изображение
if self.image and (is_new or old_image_path):
# Обрабатываем изображение с использованием SKU товара как идентификатора
# SKU гарантирует уникальность и читаемость имени файла
identifier = self.product.sku if self.product.sku else self.product.slug
# Обрабатываем изображение с использованием slug товара как идентификатора
# slug гарантирует уникальность и читаемость имени файла
identifier = self.product.slug
processed_paths = ImageProcessor.process_image(self.image, 'products', identifier=identifier)
# Сохраняем только путь к оригиналу в поле image
self.image = processed_paths['original']