Замена простого select на autocomplete с поиском для привязки атрибутов к товарам/комплектам
- Переиспользован модуль select2-product-search.js из orders - Заменен простой select на Select2 с AJAX поиском через API search_products_and_variants - Добавлена поддержка привязки как ProductKit, так и Product к значениям атрибутов - Обновлен метод _save_attributes_from_cards для обработки item_ids и item_types - Удалены дублирующиеся подключения jQuery и Select2 (используются из base.html) - Улучшен UX: живой поиск, отображение типа товара (🌹/💐), цены и наличия
This commit is contained in:
@@ -96,11 +96,6 @@ class ConfigurableProductDetailView(LoginRequiredMixin, ManagerOwnerRequiredMixi
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
# Добавляем доступные комплекты для выбора (активные, не временные)
|
||||
context['available_kits'] = ProductKit.objects.filter(
|
||||
status='active',
|
||||
is_temporary=False
|
||||
).order_by('name')
|
||||
return context
|
||||
|
||||
|
||||
@@ -138,12 +133,6 @@ class ConfigurableProductCreateView(LoginRequiredMixin, ManagerOwnerRequiredMixi
|
||||
prefix='attributes'
|
||||
)
|
||||
|
||||
# Доступные комплекты для JavaScript (для выбора при добавлении значений атрибутов)
|
||||
context['available_kits'] = ProductKit.objects.filter(
|
||||
status='active',
|
||||
is_temporary=False
|
||||
).order_by('name')
|
||||
|
||||
# Справочник атрибутов для autocomplete
|
||||
context['product_attributes'] = ProductAttribute.objects.prefetch_related('values').order_by('position', 'name')
|
||||
|
||||
@@ -247,10 +236,12 @@ class ConfigurableProductCreateView(LoginRequiredMixin, ManagerOwnerRequiredMixi
|
||||
- attributes-X-visible: видимость
|
||||
- attributes-X-DELETE: помечен ли для удаления
|
||||
- attributes-X-values: JSON массив значений параметра
|
||||
- attributes-X-kits: JSON массив ID комплектов для каждого значения
|
||||
- attributes-X-item_ids: JSON массив ID товаров/комплектов
|
||||
- attributes-X-item_types: JSON массив типов ('product' или 'kit')
|
||||
"""
|
||||
import json
|
||||
from products.models.kits import ProductKit
|
||||
from products.models.products import Product
|
||||
|
||||
# Сначала удаляем все старые атрибуты
|
||||
ConfigurableProductAttribute.objects.filter(parent=self.object).delete()
|
||||
@@ -282,9 +273,10 @@ class ConfigurableProductCreateView(LoginRequiredMixin, ManagerOwnerRequiredMixi
|
||||
|
||||
visible = self.request.POST.get(f'attributes-{idx}-visible') == 'on'
|
||||
|
||||
# Получаем значения и их привязанные комплекты
|
||||
# Получаем значения, ID и типы (kit/product)
|
||||
values_json = self.request.POST.get(f'attributes-{idx}-values', '[]')
|
||||
kits_json = self.request.POST.get(f'attributes-{idx}-kits', '[]')
|
||||
item_ids_json = self.request.POST.get(f'attributes-{idx}-item_ids', '[]')
|
||||
item_types_json = self.request.POST.get(f'attributes-{idx}-item_types', '[]')
|
||||
|
||||
try:
|
||||
values = json.loads(values_json)
|
||||
@@ -292,15 +284,21 @@ class ConfigurableProductCreateView(LoginRequiredMixin, ManagerOwnerRequiredMixi
|
||||
values = []
|
||||
|
||||
try:
|
||||
kit_ids = json.loads(kits_json)
|
||||
item_ids = json.loads(item_ids_json)
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
kit_ids = []
|
||||
item_ids = []
|
||||
|
||||
try:
|
||||
item_types = json.loads(item_types_json)
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
item_types = []
|
||||
|
||||
# Создаём ConfigurableProductAttribute для каждого значения
|
||||
for value_idx, value in enumerate(values):
|
||||
if value and value.strip():
|
||||
# Получаем соответствующий ID комплекта
|
||||
kit_id = kit_ids[value_idx] if value_idx < len(kit_ids) else None
|
||||
# Получаем соответствующие ID и тип
|
||||
item_id = item_ids[value_idx] if value_idx < len(item_ids) else None
|
||||
item_type = item_types[value_idx] if value_idx < len(item_types) else None
|
||||
|
||||
# Приготавливаем параметры создания
|
||||
create_kwargs = {
|
||||
@@ -311,13 +309,17 @@ class ConfigurableProductCreateView(LoginRequiredMixin, ManagerOwnerRequiredMixi
|
||||
'visible': visible
|
||||
}
|
||||
|
||||
# Добавляем комплект если указан
|
||||
if kit_id:
|
||||
# Добавляем комплект или товар если указан
|
||||
if item_id and item_type:
|
||||
try:
|
||||
kit = ProductKit.objects.get(id=kit_id)
|
||||
create_kwargs['kit'] = kit
|
||||
except ProductKit.DoesNotExist:
|
||||
# Комплект не найден - создаём без привязки
|
||||
if item_type == 'kit':
|
||||
kit = ProductKit.objects.get(id=item_id)
|
||||
create_kwargs['kit'] = kit
|
||||
elif item_type == 'product':
|
||||
product = Product.objects.get(id=item_id)
|
||||
create_kwargs['product'] = product
|
||||
except (ProductKit.DoesNotExist, Product.DoesNotExist):
|
||||
# Комплект/товар не найден - создаём без привязки
|
||||
pass
|
||||
|
||||
ConfigurableProductAttribute.objects.create(**create_kwargs)
|
||||
@@ -527,10 +529,12 @@ class ConfigurableProductUpdateView(LoginRequiredMixin, ManagerOwnerRequiredMixi
|
||||
- attributes-X-visible: видимость
|
||||
- attributes-X-DELETE: помечен ли для удаления
|
||||
- attributes-X-values: JSON массив значений параметра
|
||||
- attributes-X-kits: JSON массив ID комплектов для каждого значения
|
||||
- attributes-X-item_ids: JSON массив ID товаров/комплектов
|
||||
- attributes-X-item_types: JSON массив типов ('product' или 'kit')
|
||||
"""
|
||||
import json
|
||||
from products.models.kits import ProductKit
|
||||
from products.models.products import Product
|
||||
|
||||
# Сначала удаляем все старые атрибуты
|
||||
ConfigurableProductAttribute.objects.filter(parent=self.object).delete()
|
||||
@@ -562,9 +566,10 @@ class ConfigurableProductUpdateView(LoginRequiredMixin, ManagerOwnerRequiredMixi
|
||||
|
||||
visible = self.request.POST.get(f'attributes-{idx}-visible') == 'on'
|
||||
|
||||
# Получаем значения и их привязанные комплекты
|
||||
# Получаем значения, ID и типы (kit/product)
|
||||
values_json = self.request.POST.get(f'attributes-{idx}-values', '[]')
|
||||
kits_json = self.request.POST.get(f'attributes-{idx}-kits', '[]')
|
||||
item_ids_json = self.request.POST.get(f'attributes-{idx}-item_ids', '[]')
|
||||
item_types_json = self.request.POST.get(f'attributes-{idx}-item_types', '[]')
|
||||
|
||||
try:
|
||||
values = json.loads(values_json)
|
||||
@@ -572,15 +577,21 @@ class ConfigurableProductUpdateView(LoginRequiredMixin, ManagerOwnerRequiredMixi
|
||||
values = []
|
||||
|
||||
try:
|
||||
kit_ids = json.loads(kits_json)
|
||||
item_ids = json.loads(item_ids_json)
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
kit_ids = []
|
||||
item_ids = []
|
||||
|
||||
try:
|
||||
item_types = json.loads(item_types_json)
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
item_types = []
|
||||
|
||||
# Создаём ConfigurableProductAttribute для каждого значения
|
||||
for value_idx, value in enumerate(values):
|
||||
if value and value.strip():
|
||||
# Получаем соответствующий ID комплекта
|
||||
kit_id = kit_ids[value_idx] if value_idx < len(kit_ids) else None
|
||||
# Получаем соответствующие ID и тип
|
||||
item_id = item_ids[value_idx] if value_idx < len(item_ids) else None
|
||||
item_type = item_types[value_idx] if value_idx < len(item_types) else None
|
||||
|
||||
# Приготавливаем параметры создания
|
||||
create_kwargs = {
|
||||
@@ -591,13 +602,17 @@ class ConfigurableProductUpdateView(LoginRequiredMixin, ManagerOwnerRequiredMixi
|
||||
'visible': visible
|
||||
}
|
||||
|
||||
# Добавляем комплект если указан
|
||||
if kit_id:
|
||||
# Добавляем комплект или товар если указан
|
||||
if item_id and item_type:
|
||||
try:
|
||||
kit = ProductKit.objects.get(id=kit_id)
|
||||
create_kwargs['kit'] = kit
|
||||
except ProductKit.DoesNotExist:
|
||||
# Комплект не найден - создаём без привязки
|
||||
if item_type == 'kit':
|
||||
kit = ProductKit.objects.get(id=item_id)
|
||||
create_kwargs['kit'] = kit
|
||||
elif item_type == 'product':
|
||||
product = Product.objects.get(id=item_id)
|
||||
create_kwargs['product'] = product
|
||||
except (ProductKit.DoesNotExist, Product.DoesNotExist):
|
||||
# Комплект/товар не найден - создаём без привязки
|
||||
pass
|
||||
|
||||
ConfigurableProductAttribute.objects.create(**create_kwargs)
|
||||
|
||||
Reference in New Issue
Block a user