Я соединил форму для сохранения рецепта. Это использует форму и встроенный formset. У меня есть пользователи с текстовыми файлами, содержащими рецепты, и они хотели бы вырезать и вставить данные для создания записи легче. Я разработал, как заполнить часть формы после обработки входа необработанного текста, но я не могу выяснить, как заполнить встроенный formset.
Кажется, что решение почти записано здесь: http://code.djangoproject.com/ticket/12213, но я не могу вполне соединить части.
Мои модели:
#models.py
from django.db import models
class Ingredient(models.Model):
title = models.CharField(max_length=100, unique=True)
class Meta:
ordering = ['title']
def __unicode__(self):
return self.title
def get_absolute_url(self):
return self.id
class Recipe(models.Model):
title = models.CharField(max_length=255)
description = models.TextField(blank=True)
directions = models.TextField()
class Meta:
ordering = ['title']
def __unicode__(self):
return self.id
def get_absolute_url(self):
return "/recipes/%s/" % self.id
class UnitOfMeasure(models.Model):
title = models.CharField(max_length=10, unique=True)
class Meta:
ordering = ['title']
def __unicode__(self):
return self.title
def get_absolute_url(self):
return self.id
class RecipeIngredient(models.Model):
quantity = models.DecimalField(max_digits=5, decimal_places=3)
unit_of_measure = models.ForeignKey(UnitOfMeasure)
ingredient = models.ForeignKey(Ingredient)
recipe = models.ForeignKey(Recipe)
def __unicode__(self):
return self.id
Форма рецепта создается с помощью ModelForm:
class AddRecipeForm(ModelForm):
class Meta:
model = Recipe
extra = 0
И соответствующие нормы в представлении (звонит для парсинга исходных данных формы, удалены):
def raw_text(request):
if request.method == 'POST':
...
form_data = {'title': title,
'description': description,
'directions': directions,
}
form = AddRecipeForm(form_data)
#the count variable represents the number of RecipeIngredients
FormSet = inlineformset_factory(Recipe, RecipeIngredient,
extra=count, can_delete=False)
formset = FormSet()
return render_to_response('recipes/form_recipe.html', {
'form': form,
'formset': formset,
})
else:
pass
return render_to_response('recipes/form_raw_text.html', {})
С FormSet () пустой как выше я могу успешно запустить страницу. Я попробовал несколько способов подать formset количество, unit_of_measure и компоненты, включая которые я определил:
Любые предложения значительно ценятся.
Моим первым советом было бы выбрать простой выход: сохранить Recipe
и RecipeIngredient
s, а затем использовать полученный Recipe
в качестве вашего экземпляра при создании FormSet
. Вы можете захотеть добавить к своим рецептам логическое поле «проверено», чтобы указать, были ли наборы форм затем одобрены пользователем.
Однако, если вы не хотите идти по этому пути по какой-либо причине, вы сможете заполнить свои наборы форм следующим образом:
Мы предполагаем, что вы разобрали текстовые данные на ингредиенты рецепта, и есть список словарей, подобных этому:
recipe_ingredients = [
{
'ingredient': 2,
'quantity': 7,
'unit': 1
},
{
'ingredient': 3,
'quantity': 5,
'unit': 2
},
]
Числа в полях «ингредиент» и «единица измерения» являются значениями первичного ключа для соответствующих ингредиентов и объектов единиц измерения. Я предполагаю, что вы уже сформулировали какой-то способ сопоставления текста с ингредиентами в вашей базе данных или создания новых.
Затем вы можете сделать:
RecipeFormset = inlineformset_factory(
Recipe,
RecipeIngredient,
extra=len(recipe_ingredients),
can_delete=False)
formset = RecipeFormset()
for subform, data in zip(formset.forms, recipe_ingredients):
subform.initial = data
return render_to_response('recipes/form_recipe.html', {
'form': form,
'formset': formset,
})
Это устанавливает свойство initial
каждой формы в наборе форм в словарь из вашего списка recipe_ingredients
. Мне кажется, это работает с точки зрения отображения набора форм, но я еще не пробовал сохранять.