Home > Back-end >  Django models for creating multiple variations of t-shirts
Django models for creating multiple variations of t-shirts

Time:09-16

I'm creating an ecommerce store that sells T-shirts, hoodies, mugs, shot glasses, etc. For the t-shirts and hoodies there are sizes and sometimes color associated with each product. I'm trying to add multiple variations for each product. Here's my model.py code:

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

The way it appears right now in my admin interface there is a name, attribute, value, and price (only named relevant fields for clarity). If I add a product like such: "t-shirt_1, size, sm, 17.98", then the next item I need to add is "t-shirt_1, size, med, 17.98" and so forth (2xl and above, price goes up). Is there a way to simplify this where I just enter the product name once, then add all sizes and associated pricing, as well as inventory tracking (haven't created field yet) for each size within the product?

Thanks in advance for some guidance

CodePudding user response:

Remove corresponding attribute fields from Product model and create OneToMany relationship between Product and ProductAttribute. Then create separate Size and Color models, and relate them to ProductAttribute with ManyToMany relationship:

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)
    ...

Now you can create Product object, then go to ProductAttribute to relate corresponding product object with product attribute model and add each attribute of that product (sizes or colors). Whenever you need to get product size or color you can do it as follows:

# 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

CodePudding user response:

Not required

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

    def __str__(self):
        return self.name
  • Related