refactor: Двухэтапное создание комплектов товаров

Реализован современный двухэтапный подход к созданию комплектов:

**Шаг 1: Создание базовой информации** (productkit_create.html)
- Упрощённая форма только с базовой информацией
- Название, описание, категории, теги
- Фотографии с предпросмотром
- Настройки ценообразования
- Чистый современный UI с breadcrumbs
- Прогрессивное раскрытие (collapsible секции)

**Шаг 2: Добавление товаров** (productkit_edit.html)
- Автоматический redirect после создания
- Работа с товарами через существующий функционал
- Улучшенный заголовок с указанием шага

**Изменения в коде:**
- ProductKitCreateView: упрощён, убраны formsets
- ProductKitUpdateView: использует новый шаблон
- productkit_form.html → productkit_edit.html
- Новый шаблон productkit_create.html

**Преимущества:**
 Простая и надёжная логика сохранения
 Нет проблем с disabled полями в formsets
 Понятный UX с чёткими шагами
 Современный дизайн с иконками Bootstrap
 Предпросмотр фото перед загрузкой

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-23 16:05:13 +03:00
parent dd2b1f21f7
commit 9d5ce11951
3 changed files with 1469 additions and 46 deletions

View File

@@ -83,72 +83,47 @@ class ProductKitListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
class ProductKitCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
"""
View для создания нового комплекта с компонентами.
View для создания нового комплекта (только базовая информация).
После создания redirect на страницу редактирования для добавления товаров.
"""
model = ProductKit
form_class = ProductKitForm
template_name = 'products/productkit_form.html'
template_name = 'products/productkit_create.html'
permission_required = 'products.add_productkit'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
if self.request.POST:
context['kititem_formset'] = KitItemFormSetCreate(self.request.POST, instance=self.object)
else:
context['kititem_formset'] = KitItemFormSetCreate(instance=self.object)
return context
def form_valid(self, form):
# Получаем формсет из POST
kititem_formset = KitItemFormSetCreate(self.request.POST, instance=self.object)
try:
with transaction.atomic():
# Сохраняем основную форму
self.object = form.save()
# Проверяем валидность формсета
if kititem_formset.is_valid():
try:
with transaction.atomic():
# Сохраняем основную форму
self.object = form.save()
# Обработка фотографий
handle_photos(self.request, self.object, ProductKitPhoto, 'kit')
# Сохраняем компоненты
kititem_formset.instance = self.object
kititem_formset.save()
messages.success(
self.request,
f'Комплект "{self.object.name}" создан! Теперь добавьте товары в комплект.'
)
# Обработка фотографий
handle_photos(self.request, self.object, ProductKitPhoto, 'kit')
# Всегда redirect на страницу редактирования для добавления товаров
return redirect('products:productkit-update', pk=self.object.pk)
messages.success(self.request, f'Комплект "{self.object.name}" успешно создан!')
# Проверяем, какую кнопку нажали
if self.request.POST.get('action') == 'continue':
return redirect('products:productkit-update', pk=self.object.pk)
else:
return redirect('products:productkit-list')
except Exception as e:
messages.error(self.request, f'Ошибка при сохранении: {str(e)}')
return self.form_invalid(form)
else:
# Если формсет невалиден, показываем форму с ошибками
messages.error(self.request, 'Пожалуйста, исправьте ошибки в компонентах комплекта.')
except Exception as e:
messages.error(self.request, f'Ошибка при сохранении: {str(e)}')
return self.form_invalid(form)
def form_invalid(self, form):
# Получаем формсет для отображения ошибок
context = self.get_context_data(form=form)
return self.render_to_response(context)
def get_success_url(self):
return reverse_lazy('products:productkit-list')
# Этот метод не используется, т.к. мы делаем redirect в form_valid
return reverse_lazy('products:productkit-update', kwargs={'pk': self.object.pk})
class ProductKitUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
"""
View для редактирования существующего комплекта.
View для редактирования существующего комплекта и добавления товаров.
"""
model = ProductKit
form_class = ProductKitForm
template_name = 'products/productkit_form.html'
template_name = 'products/productkit_edit.html'
permission_required = 'products.change_productkit'
def get_context_data(self, **kwargs):