Как правильно реализовать динамический список значений в джанго модели?

Я делаю интернет-магазин на джанго. Мне нужно сделать так, чтоб при детальном осмотре товара можно било выбирать его параметры прежде чем положить в корзину. Например: товар 'телефон' - (его варианти) - цвет(черный, белый, синий), объем памяти(64гб, 128гб) и тд.Соответственно мне нужно реализовать списки значений которые может, при необходимости изменять владелец сайта, например, добавить к параметру 'объем памяти' опцию 32гб. Еще, какбы запись телефона в бд должна бить одна, а вот покупатель уже может разные версии одного и того же телефона покупать.

Вот пример как оно должно бить на сайте:

введите сюда описание изображения

я сделал такие модели:

class Product(models.Model):
    name = models.CharField(verbose_name='Назва', max_length=150)
    price = models.FloatField(verbose_name='Ціна', validators=[validators.MinValueValidator(0.01)])
    model = models.CharField(verbose_name='Модель', max_length=150)
    manufacturer = models.CharField(verbose_name='Виробник', max_length=150)
    availability = models.BooleanField(default=True)
    average_rating = models.FloatField(verbose_name='Рейтинг', default=None)
    slug = AutoSlugField(populate_from='name', max_length=150, unique=True, db_index=True, verbose_name="URL")

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = 'Товар'
        verbose_name_plural = 'Товари'


class ProductParameter(models.Model):
    product = models.ForeignKey('Product', verbose_name='Опція до товару', on_delete=models.CASCADE)
    name = models.CharField(max_length=50, verbose_name='Параметр')

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = 'Параметр товару'
        verbose_name_plural = 'Параметри товарів'


class ParameterOptions(models.Model):
    parameter = models.ForeignKey('ProductParameter', verbose_name='Опція до параметру', on_delete=models.CASCADE)
    name = models.CharField(max_length=50, verbose_name='Опція')

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = 'Опція до параметру'
        verbose_name_plural = 'Опція до параметрів'

Незнаю правильно ли ето и есть ли какие нибудь другие, лучшие решения. Подскажите пожалуйста...


Ответы (1 шт):

Автор решения: Mikhailo

в итоге, немного подумав сделал такие модели:

class Product(models.Model):
    name = models.CharField(verbose_name='Назва', max_length=150)
    price = models.FloatField(verbose_name='Ціна', validators=[validators.MinValueValidator(0.01)])
    model = models.CharField(verbose_name='Модель', max_length=150, blank=True)
    manufacturer = models.ForeignKey(
        'Manufacturer',
        verbose_name='Виробник',
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        related_name='products'
    )
    category = models.ForeignKey(
        'Subcategory',
        verbose_name='Категорія',
        on_delete=models.PROTECT,
        related_name='products'
    )
    availability = models.BooleanField(verbose_name='В наявності', default=True)
    average_rating = models.FloatField(verbose_name='Рейтинг', default=0)
    photo = models.ImageField(verbose_name='Фото', upload_to='photos_product/%Y/%m/%d/')
    description = models.TextField(verbose_name='Опис товару')
    evaluated_cnt = models.PositiveBigIntegerField(verbose_name='Оцінено раз', default=0)
    added = models.DateField(verbose_name='Додано', auto_now_add=True)
    discount = models.PositiveSmallIntegerField(verbose_name='Знижка', default=0, blank=True)
    slug = AutoSlugField(populate_from='name', max_length=150, unique=True, db_index=True, verbose_name="URL")

    def get_reduced_price(self):
        if self.discount:
            return self.price - (self.price * self.discount/100)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = 'Товар'
        verbose_name_plural = 'Товари'
        ordering = ['-added']


class ProductParameter(models.Model):
    name = models.CharField(max_length=50, verbose_name='Назва типу параметру')

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = 'Параметр товару'
        verbose_name_plural = 'Параметри товарів'


class ProductOptions(models.Model):
    name = models.CharField(max_length=50, verbose_name='Варіант товару')
    parameter = models.ForeignKey(
        'ProductParameter',
        verbose_name='Тип варіанту',
        on_delete=models.CASCADE,
    )
    product = models.ForeignKey(
        'Product',
        verbose_name='Продукт',
        on_delete=models.CASCADE,
        related_name='options'
    )
    surcharge = models.FloatField(verbose_name='Доплата', blank=True, null=True, help_text='необов\'язково')

    def __str__(self):
        return self.name

для меня подходят, работать удобно.

незнаю, может кому то ето полезно будет...

→ Ссылка