diff --git a/artel/store/admin.py b/artel/store/admin.py index ffe0108..104d31f 100644 --- a/artel/store/admin.py +++ b/artel/store/admin.py @@ -10,38 +10,42 @@ from wagtail.admin.forms.models import WagtailAdminModelForm from store import models -class ProductConfigAdmin(ModelAdmin): - model = models.ProductConfig - list_display = ("author__name", "color", "price") - search_fields = ("author__name", "color", "price") +class ProductAuthorAdmin(ModelAdmin): + model = models.ProductAuthor + list_display = ("name", ) + + +class ProductCategoryAdmin(ModelAdmin): + model = models.ProductCategory + list_display = ("name", ) + + +class ProductCategoryParamAdmin(ModelAdmin): + model = models.ProductCategoryParam + list_display = ("key", "param_type") class ProductTemplateAdmin(ModelAdmin): model = models.ProductTemplate - list_display = ("title", ) - - -class ProductAdminForm(WagtailAdminModelForm): - - template_title = fields.CharField() - template_code = fields.CharField() - template_description = fields.CharField() - - class Meta: - fields = ("template_title", "template_code", "template_description") - model = models.Product + list_display = ("title", "code") class ProductAdmin(ModelAdmin): model = models.Product - form = ProductAdminForm + list_display = ("title", "price") class StoreAdminGroup(ModelAdminGroup): menu_label = "Store" menu_icon = 'folder-open-inverse' menu_order = 200 - items = (ProductConfigAdmin, ProductTemplateAdmin, ProductAdmin) - + items = ( + ProductAuthorAdmin, + ProductCategoryAdmin, + ProductCategoryParamAdmin, + ProductTemplateAdmin, + ProductAdmin + ) + modeladmin_register(StoreAdminGroup) diff --git a/artel/store/migrations/0001_initial.py b/artel/store/migrations/0001_initial.py index 046c795..5c9f769 100644 --- a/artel/store/migrations/0001_initial.py +++ b/artel/store/migrations/0001_initial.py @@ -1,7 +1,8 @@ -# Generated by Django 4.1.8 on 2023-04-25 22:22 +# Generated by Django 4.1.9 on 2023-05-10 19:40 from django.db import migrations, models import django.db.models.deletion +import modelcluster.fields class Migration(migrations.Migration): @@ -12,6 +13,16 @@ class Migration(migrations.Migration): ] operations = [ + migrations.CreateModel( + name='Product', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('price', models.FloatField()), + ], + options={ + 'abstract': False, + }, + ), migrations.CreateModel( name='ProductAuthor', fields=[ @@ -19,6 +30,37 @@ class Migration(migrations.Migration): ('name', models.CharField(max_length=255)), ], ), + migrations.CreateModel( + name='ProductCategory', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='ProductCategoryParam', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.CharField(max_length=200)), + ('param_type', models.CharField(choices=[('int', 'Int'), ('str', 'String'), ('float', 'Float')], max_length=200)), + ('category', modelcluster.fields.ParentalKey(on_delete=django.db.models.deletion.CASCADE, related_name='category_params', to='store.productcategory')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='TemplateParamValue', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('value', models.CharField(max_length=255)), + ('param', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='store.productcategoryparam')), + ('product', modelcluster.fields.ParentalKey(on_delete=django.db.models.deletion.CASCADE, related_name='param_values', to='store.product')), + ], + ), migrations.CreateModel( name='ProductTemplate', fields=[ @@ -26,32 +68,24 @@ class Migration(migrations.Migration): ('title', models.CharField(max_length=255)), ('code', models.CharField(max_length=255)), ('description', models.TextField()), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='store.productauthor')), + ('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='store.productcategory')), ], + options={ + 'abstract': False, + }, ), migrations.CreateModel( name='ProductImage', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('image', models.ImageField(upload_to='')), - ('template', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='images', to='store.producttemplate')), + ('template', modelcluster.fields.ParentalKey(on_delete=django.db.models.deletion.CASCADE, related_name='images', to='store.producttemplate')), ], ), - migrations.CreateModel( - name='ProductConfig', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('color', models.CharField(max_length=255)), - ('size', models.CharField(max_length=50)), - ('price', models.FloatField()), - ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='store.productauthor')), - ], - ), - migrations.CreateModel( - name='Product', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('config', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='store.productconfig')), - ('template', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='store.producttemplate')), - ], + migrations.AddField( + model_name='product', + name='template', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='store.producttemplate'), ), ] diff --git a/artel/store/models.py b/artel/store/models.py index 2f08f43..8877886 100644 --- a/artel/store/models.py +++ b/artel/store/models.py @@ -1,33 +1,94 @@ from django.db import models +from modelcluster.models import ClusterableModel +from modelcluster.fields import ParentalKey +from wagtail.admin.panels import ( + FieldPanel, + InlinePanel +) +from wagtail.models import Orderable + class ProductAuthor(models.Model): name = models.CharField(max_length=255) - # TODO - author contact info? maybe foreignkey with user -class ProductTemplate(models.Model): + def __str__(self): + return self.name + + +class ProductCategory(ClusterableModel): + name = models.CharField(max_length=255) + + def __str__(self): + return self.name + + panels = [ + FieldPanel("name"), + InlinePanel("category_params") + ] + + +class CategoryParamTypeChoices(models.TextChoices): + INT = "int" + STRING = "str" + FLOAT = "float" + + +class ProductCategoryParam(ClusterableModel): + category = ParentalKey(ProductCategory, on_delete=models.CASCADE, related_name="category_params") + key = models.CharField(max_length=200) + param_type = models.CharField(max_length=200, choices=CategoryParamTypeChoices.choices) + + def __str__(self): + return self.key + + +class ProductTemplate(ClusterableModel): + category = models.ForeignKey(ProductCategory, on_delete=models.CASCADE) + author = models.ForeignKey(ProductAuthor, on_delete=models.CASCADE) title = models.CharField(max_length=255) code = models.CharField(max_length=255) description = models.TextField() + def __str__(self): + return self.title + def get_images(self): return self.images.objects.all().values_list("image") + panels = [ + FieldPanel("category"), + FieldPanel("author"), + FieldPanel('title'), + FieldPanel('code'), + FieldPanel('description'), + InlinePanel("images") + ] + class ProductImage(models.Model): - template = models.ForeignKey( + template = ParentalKey( ProductTemplate, on_delete=models.CASCADE, related_name="images" ) image = models.ImageField() -class ProductConfig(models.Model): - author = models.ForeignKey(ProductAuthor, on_delete=models.CASCADE) - color = models.CharField(max_length=255) - size = models.CharField(max_length=50) +class Product(ClusterableModel): + template = models.ForeignKey(ProductTemplate, on_delete=models.CASCADE) price = models.FloatField() + panels = [ + FieldPanel("template"), + FieldPanel("price"), + InlinePanel("param_values") + ] -class Product(models.Model): - template = models.ForeignKey(ProductTemplate, on_delete=models.CASCADE) - config = models.ForeignKey(ProductConfig, on_delete=models.CASCADE) + @property + def title(self): + return f"{self.template.title} - {self.price}" + + +class TemplateParamValue(models.Model): + param = models.ForeignKey(ProductCategoryParam, on_delete=models.CASCADE) + product = ParentalKey(Product, on_delete=models.CASCADE, related_name="param_values") + value = models.CharField(max_length=255)