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