Django-модели для создания множества вариантов футболок

Я создаю магазин электронной коммерции, который продает футболки, толстовки, кружки, рюмки и т.д. Для футболок и толстовок есть размеры и иногда цвет, связанный с каждым продуктом. Я пытаюсь добавить несколько вариантов для каждого продукта. Вот мой код model.py:

class Category(models.Model):
    name = models.CharField(max_length = 255, db_index=True, null=True, blank=True)
    slug = models.SlugField(max_length=255, unique=True, default='')
    class Meta:
        verbose_name_plural = 'categories'\

    def get_absolute_url(self):
        return reverse('main:category_list', args=[self.slug])
    def __str__(self):
        return self.name

class Attribute(models.Model):
    name = models.CharField(max_length = 255,   default='')

    def __str__(self):
        return self.name

class ProductAttribute(models.Model):
    attribute = models.ManyToManyField(Attribute, through='Product')
    value = models.CharField(max_length = 255, null=True, blank=True)

    def __str__(self):
        return self.value

class Product(models.Model):
    category = models.ForeignKey(Category, on_delete=models.CASCADE, null=True, blank=True)
    name = models.CharField(max_length = 255, default='')
    description = models.TextField(blank=True)
    image = models.ImageField(upload_to='products/', null=True, blank=True)
    slug = models.SlugField(max_length = 255, default='')
    price = models.DecimalField(max_digits=4,decimal_places=2)
    has_attributes = models.BooleanField(default=False)
    attribute = models.ForeignKey(Attribute, on_delete=models.CASCADE, null=True, blank=True)
    value = models.ForeignKey(ProductAttribute, on_delete=models.CASCADE, null=True, blank=True)
    class Meta:
        ordering=(['name'])

    def get_absolute_url(self):
        return reverse('main:product_detail', args=[self.slug])

    def __str__(self):
        return self.name

Сейчас в моем интерфейсе администратора есть название, атрибут, значение и цена (для наглядности названы только соответствующие поля). Если я добавляю товар, например: "футболка_1, размер, sm, 17.98", то следующий товар, который мне нужно добавить, будет "футболка_1, размер, med, 17.98" и так далее (2xl и выше, цена увеличивается). Есть ли способ упростить эту задачу, когда я просто ввожу название товара один раз, затем добавляю все размеры и соответствующие цены, а также отслеживаю запасы (поле еще не создано) для каждого размера внутри товара?

Заранее спасибо за подсказки

Удалите соответствующие поля атрибутов из модели Product и создайте отношения OneToMany между Product и ProductAttribute. Затем создайте отдельные модели Size и Color и свяжите их с ProductAttribute с помощью ManyToMany отношений:

class Product(models.Model):
    category = models.ForeignKey(Category, on_delete=models.CASCADE, null=True, blank=True)
    name = models.CharField(max_length = 255, default='')
    description = models.TextField(blank=True)
    image = models.ImageField(upload_to='products/', null=True, blank=True)
    slug = models.SlugField(max_length = 255, default='')
    price = models.DecimalField(max_digits=4,decimal_places=2)
    has_attributes = models.BooleanField(default=False)
    ...


class ProductAttribute(models.Model):
    product = models.ForeignKey('Product', related_name="product_attrs", on_delete=models.CASCADE)
    sizes = models.ManyToManyField('Size', related_name="product_sizes", null=True, blank=True)
    colors = models.ManyToManyField('Product', related_name="product_colors", null=True, blank=True)
    ...


class Size(models.Model):
    size_num = models.CharField(max_length=10)
    ...


class Color(models.Model):
    color_name = models.CharField(max_length=15)
    ...

Теперь вы можете создать объект Product, затем перейти к ProductAttribute, чтобы связать соответствующий объект продукта с моделью атрибутов продукта и добавить каждый атрибут этого продукта (размеры или цвета). Когда вам понадобится получить размер или цвет продукта, вы можете сделать это следующим образом:

# let's say you need to get sizes of last product
p = Product.objects.last()
sizes = p.product_attrs.sizes.all()
# ↑ returns queryset containing all sizes of product

Не требуется

class Attribute(models.Model): name = models.CharField(max_length = 255, default='')

def __str__(self):
    return self.name
Вернуться на верх