Лучший способ добавить несколько полей в эту модель?
В моем проекте Django у меня есть модель для рецепта напитка, которая позволяет вводить до 10 ингредиентов плюс их количество. Мне интересно, возможно ли сделать это более DRY способом, чем я делаю сейчас? Вот модель, которую я использую в настоящее время:
class Recipe(models.Model):
ingr_name1 = models.CharField(max_length=250, verbose_name='Ingredient')
ingr_amount1 = models.DecimalField(max_digits=5, decimal_places=1, verbose_name='Amount')
ingr_name2 = models.CharField(max_length=250, blank=True, null=True, verbose_name='Ingredient')
ingr_amount2 = models.DecimalField(max_digits=5, decimal_places=1,blank=True, null=True, verbose_name='Amount')
ingr_name3 = models.CharField(max_length=250,blank=True, null=True, verbose_name='Ingredient')
ingr_amount3 = models.DecimalField(max_digits=5, decimal_places=1,blank=True, null=True, verbose_name='Amount')
ingr_name4 = models.CharField(max_length=250,blank=True, null=True, verbose_name='Ingredient')
ingr_amount4 = models.DecimalField(max_digits=5, decimal_places=1,blank=True, null=True, verbose_name='Amount')
ingr_name5 = models.CharField(max_length=250,blank=True, null=True, verbose_name='Ingredient')
ingr_amount5 = models.DecimalField(max_digits=5, decimal_places=1,blank=True, null=True, verbose_name='Amount')
ingr_name6 = models.CharField(max_length=250,blank=True, null=True, verbose_name='Ingredient')
ingr_amount6 = models.DecimalField(max_digits=5, decimal_places=1,blank=True, null=True, verbose_name='Amount')
ingr_name7 = models.CharField(max_length=250,blank=True, null=True, verbose_name='Ingredient')
ingr_amount7 = models.DecimalField(max_digits=5, decimal_places=1,blank=True, null=True, verbose_name='Amount')
ingr_name8 = models.CharField(max_length=250,blank=True, null=True, verbose_name='Ingredient')
ingr_amount8 = models.DecimalField(max_digits=5, decimal_places=1,blank=True, null=True, verbose_name='Amount')
ingr_name9 = models.CharField(max_length=250,blank=True, null=True, verbose_name='Ingredient')
ingr_amount9 = models.DecimalField(max_digits=5, decimal_places=1,blank=True, null=True, verbose_name='Amount')
ingr_name10 = models.CharField(max_length=250,blank=True, null=True, verbose_name='Ingredient')
ingr_amount10 = models.DecimalField(max_digits=5, decimal_places=1,blank=True, null=True, verbose_name='Amount')
drink_name = models.CharField(max_length=250,blank=True, null=True, verbose_name='Drink name')
drink_story = models.TextField()
drink_picture = ResizedImageField(upload_to='drinks/', null=True, blank=True)
def __str__(self):
return self.drink_name
Вы можете подумать об альтернативном поле модели, таком как JSONField или TextField. JSONFields является хорошим вариантом, если вы:
- Не знаю, сколько ingr_amounts& ingr_names используется .
- Если вы хотите обрабатывать их вместе. В рамках текущей модели вам придется делать очистку на основе каждого self.ingr, с json-полем вы можете сделать это с одним self.my_json_field. .
Кроме того, есть и недостатки, особенно при запросе и обновлении json-полей, это может стать сложнее. Поэтому, прежде чем использовать его, пожалуйста, ознакомьтесь с этим, например, JSONField, json query
*Вы также можете, если это соответствует вашим потребностям, создать новую модель с обоими полями и связать ее с другой моделью через ForeignKey
Один из вариантов - сделать Ingredient собственной моделью и добавить его в качестве поля many to many в модель рецепта. Затем, основываясь на этом ответе, вы можете ограничить количество ингредиентов до 10, добавив функцию ingredients_changed()
в модель рецепта.
Ниже приведен непроверенный код:
class Ingredient(model.Model):
name = models.CharField()
amount = models.CharField()
class Recipe(models.Model):
ingredients = models.ManyToManyField(Ingredient)
def ingredients_changed(recipe, **kwargs):
if kwargs['instance'].ingredients.count() > 10:
raise ValidationError("You can't assign more than 10 ingredients")