- мне надо чтобы порядок размеров в "Выбранные размеры" не сбрасывался при редактировании товара на то как они были добавлены в базу данных, а порядок был такой как я их добавил в таблицу "Выбранные размеры" из таблицы "Доступные размеры". Я пробовал разные решения, но так и не нашел способ осуществить задуманное, помогите!
sizes = models.ManyToManyField('Size', related_name="products", blank=True, verbose_name=_('Sizes'))
size_order = models.CharField(max_length=255, blank=True, default="") 1.class ProductAdmin(admin.ModelAdmin):
list_display = (
"sku",
"name",
"category",
"price",
"stock_quantity",
"is_new",
"is_on_sale",
"popularity",
)
search_fields = ("name", "sku", "slug", "category__name")
list_filter = (CategoryTreeFilter, "is_new", "is_on_sale")
exclude = ["popularity", "slug"]
filter_horizontal = ("sizes", "colors", "compositions")
inlines = [ProductImageInline]
form = ProductForm
class Media:
js = ("admin/js/custom_product.js",)
def formfield_for_manytomany(self, db_field, request, **kwargs):
if db_field.name == "sizes":
obj_id = request.resolver_match.kwargs.get("object_id")
if obj_id:
try:
product = Product.objects.get(pk=obj_id)
order_ids = product.size_order.split(",") if product.size_order else []
sizes = Size.objects.filter(id__in=order_ids).order_by(
Case(*[When(id=int(size_id), then=pos) for pos, size_id in enumerate(order_ids)])
)
kwargs["queryset"] = sizes
except Product.DoesNotExist:
pass
return super().formfield_for_manytomany(db_field, request, **kwargs)
def save_model(self, request, obj, form, change):
super().save_model(request, obj, form, change)
images = form.cleaned_data.get('images')
if images:
for image in images:
if image:
ProductImage.objects.create(product=obj, image=image)
admin.site.register(Product, ProductAdmin) 2.class ProductForm(forms.ModelForm):
images = MultipleFileField(required=False, label=_("Images"))
size_order = forms.CharField(widget=forms.HiddenInput(), required=False)
class Meta:
model = Product
fields = [
'sku',
'name',
'name_ru',
'category',
'price',
'old_price',
'stock_quantity',
'is_new',
'is_on_sale',
'is_on_promo',
'colors',
'sizes',
'description',
'description_ru',
'compositions',
'images',
]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['sku'].widget.attrs['readonly'] = True
def save(self, commit=True):
instance = super().save(commit=False)
if commit:
instance.save()
if self.cleaned_data.get("size_order"):
order_ids = self.cleaned_data["size_order"]
if isinstance(order_ids, str):
order_ids = order_ids.split(",")
instance.size_order = ','.join(order_ids)
instance.save()
sizes = Size.objects.filter(id__in=order_ids)
ordered_sizes = sorted(sizes, key=lambda size: order_ids.index(str(size.id)))
instance.sizes.set(ordered_sizes)
return instance
def clean_images(self):
images = self.cleaned_data.get('images')
if isinstance(images, list):
return images
return []
def clean_name(self):
name = self.cleaned_data.get('name')
if Product.objects.filter(name=name).exclude(id=self.instance.id).exists():
raise forms.ValidationError(_('A product with this name already exists.'))
return name
def clean_name_ru(self):
name_ru = self.cleaned_data.get('name_ru')
if Product.objects.filter(name_ru=name_ru).exclude(id=self.instance.id).exists():
raise forms.ValidationError(_('A product with this Russian name already exists.'))
return name_ru 3.Я пробовал это делать через инлайн, но мне не подходит инлайн, оно выглядит в админке не так как надо. 4.Я пробовал это делать через JavaScript чтобы отслеживать когда добавляются размеры в таблицу и потом это передавать в форму. Мне нужен примерный алгоритм действий.