Django. Получение данных из Queryset
Есть книга рецептов, в которой перечислены компоненты рецепта и их процентное соотношение. Нужен функционал в виде формы, в которую пользователь вводи число - размер партии, и на выходе получает рецепт на заданный размер партии.
models.py
class Recipe(models.Model):
recipe_name = models.CharField(max_length=200, verbose_name='Название рецепта')
mass = models.FloatField(default=0, verbose_name='Общая масса')
category = models.ForeignKey(Category, on_delete=models.CASCADE, default=0)
def save(self, *args, **kwargs):
ings = self.ingredient_set.all()
for ing in ings:
ing.concentration = ing.mass / self.mass
ing.save()
return super(Recipe, self).save(*args, **kwargs)
def __str__(self):
return self.recipe_name
class Ingredient(models.Model):
recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE, related_name="ingredient_set")
ingredient = models.CharField('Ингредиент',max_length=200)
mass = models.FloatField('Масса', default=0)
concentration = models.FloatField('Концентрация',default=-1)
def __str__(self):
return self.ingredient
def save(self, *args, **kwargs):
if not self.pk:
self.recipe.mass += self.mass
self.recipe.save()
else:
prev_mass = Ingredient.objects.get(pk=self.pk).mass
if prev_mass != self.mass:
self.recipe.mass += self.mass - prev_mass
self.recipe.save()
self.concentration = (self.mass / self.recipe.mass) * 100
return super(Ingredient, self).save(*args, **kwargs)
def delete(self, *args, **kwargs):
self.recipe.mass -= self.mass
self.recipe.save()
return super(Ingredient, self).delete(*args, **kwargs)
views.py
def batch(request, pk):
recipe_id = Recipe.objects.get(pk=pk)
recipe = recipe_id.ingredient_set.values()
batch_size = request.POST.get('batch_size')
if request.method == 'POST':
form = RecipeBatchForm(request.POST)
if form.is_valid():
batch = recipe.ingredient.concentration/100*batch_size
return batch
else:
form = RecipeBatchForm()
return render(request, 'recipes/recipe_batch.html', {'form': form, 'batch': batch, 'batch_size': batch_size, 'recipe_id': recipe_id})
Выдает ошибку 'QuerySet' object has no attribute 'ingredient', хотя в local vars в recipe все нужные мне данные есть - <QuerySet [{'id': 11, 'recipe_id': 2, 'ingredient': 'Вода', 'mass': 37.8, 'concentration': 81.203007518797}, и так же для остальных компонентов.
Как правильно рассчитать batch и вывести его в шаблоне?
Ответы (2 шт):
В вашем случае, переменная
recipeэто список объектов. И вы пытаетесь у этого списка вызвать методingredient. В примере ингредиент один у рецепта - вода. Но ведь это связь один ко многим и ингредиентов может быть много. Соответственно, вам надо рассчитать размер порции для каждого из них.У вас неудачные названия переменных. В
recipe_idу вас никакой не id, а целыйRecipe. Вrecipeу вас неRecipe, а список словарей из полей ингредиентов. В объектеIngredientесть полеingredient, хотя граздо лучше было бы назвать егоname, чтобы не вносить путаницу.Нет необходимости брать только values от игредиентов.
В общем, примерно так
def batch(request, pk):
recipe = Recipe.objects.get(pk=pk) # Получаем объект рецепта
# Перебираем ингредиенты и считаем размер порции для каждого
batches = []
for ingredient in recipe.ingredient_set.all():
batch = ingredient.concentration / 100 * batch_size
batches.append({ingredient.id: batch})
Пример условный, т.к. не знаю точно ваших задач.