Implement M2M architecture for ConfigurableKitProduct variants with dynamic attribute selection
This commit introduces a complete refactoring of the variable product system:
1. **New Model**: ConfigurableKitOptionAttribute - M2M relationship between variants and attribute values
- Replaces TextField-based attribute storage with proper database relationships
- Ensures one value per attribute per variant through unique_together constraint
- Includes indexes on both option and attribute fields for query performance
2. **Form Refactoring**:
- Removed static 'attributes' field from ConfigurableKitOptionForm
- Added dynamic field generation in __init__ based on parent attributes
- Creates ModelChoiceField for each attribute (e.g., attribute_Длина, attribute_Упаковка)
- Enhanced BaseConfigurableKitOptionFormSet validation to check all attributes are filled
3. **View Updates**:
- Modified ConfigurableKitProductCreateView.form_valid() to save M2M relationships
- Modified ConfigurableKitProductUpdateView.form_valid() with same logic
- Uses transaction.atomic() for data consistency
4. **Template & JS Enhancements**:
- Reordered form so attributes section appears before variants
- Fixed template syntax: changed from field.name.startswith to "attribute_" in field.name
- Updated JavaScript to dynamically generate attribute select fields when adding variants
- Properly handles formset naming convention (options-{idx}-attribute_{name})
5. **Database Migrations**:
- Created migration 0005 to alter ConfigurableKitOption.attributes to JSONField (for future use)
- Created migration 0006 to add ConfigurableKitOptionAttribute model
6. **Tests**:
- Added test_configurable_simple.py for model/form verification
- Added test_workflow.py for complete end-to-end testing
- All tests passing successfully
Features:
✓ All attributes required for each variant if defined on parent
✓ One value per attribute per variant (unique_together constraint)
✓ One default variant per product (formset validation)
✓ Dynamic form field generation based on parent attributes
✓ Atomic transactions for multi-part operations
✓ Proper error messages per variant number
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.0.10 on 2025-11-18 15:49
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('products', '0004_configurablekitproductattribute'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='configurablekitoption',
|
||||
name='attributes',
|
||||
field=models.JSONField(blank=True, default=dict, help_text='Структурированные атрибуты. Пример: {"length": "60", "color": "red"}', verbose_name='Атрибуты варианта'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,28 @@
|
||||
# Generated by Django 5.0.10 on 2025-11-18 16:48
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('products', '0005_alter_configurablekitoption_attributes'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ConfigurableKitOptionAttribute',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('attribute', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='products.configurablekitproductattribute', verbose_name='Значение атрибута')),
|
||||
('option', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='attributes_set', to='products.configurablekitoption', verbose_name='Вариант')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Атрибут варианта',
|
||||
'verbose_name_plural': 'Атрибуты варианта',
|
||||
'unique_together': {('option', 'attribute')},
|
||||
'indexes': [models.Index(fields=['option'], name='products_co_option__93b9f7_idx'), models.Index(fields=['attribute'], name='products_co_attribu_ccc6d9_idx')],
|
||||
},
|
||||
),
|
||||
]
|
||||
Reference in New Issue
Block a user