2010-07-19 76 views
6

我已经放在一起来保存配方。它使用了一个表单和一个内联formset。我有用户使用含有食谱的文本文件,他们希望剪切和粘贴数据以使输入更容易。我已经计算出如何在处理原始文本输入后填充表单部分,但我无法弄清楚如何填充内联表单。Django Inline Formsets的初始数据

似乎这个解决方案几乎拼写在这里: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与配料:

  • 设置初始数据,但不用于在线表单集
  • 传入一个字典工作,但其产生的管理形式错误
  • 打得四处初始化,但我有点不在我的深度有

不胜感激的任何建议。

回答

19

我的第一个建议是采取简单的出路:保存RecipeRecipeIngredient s,则使得FormSet使用时所产生的Recipe为您的实例。您可能需要将“已审核”布尔字段添加到您的食谱中,以指示该表单集是否被用户批准。

但是,如果你不希望走这条路不管什么原因,你应该能够来填充表单集是这样的:

我们假设你已经分析的文本数据转换成配方成分,并有一个像这样的字典的列表:

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列表设置为一本字典。它似乎对我来说显示formset,但我还没有尝试保存。

+0

伟大的建议亚兰,非常感谢你。我会在今天尝试这些选项。我特别喜欢有一个简单的选择... – Sinidex 2010-07-19 14:16:26

+0

使用zip绝对的作品,我可以证实,以通常的方式保存表单也可以。正如你所指出的,我仍然需要将解析后的文本与相关的成分和度量单位相匹配,但我认为这应该是可以管理的。好的解决方案 – Sinidex 2010-07-19 17:04:26

+1

是的,是的。这是一个很好的解决方案!我很难做到这一点。我首先研究如何构建集合中的每个表单。然后在一个表单(而不是formset)的基础上实现了初始*做*工作。在zip中,我们相信™ – Flowpoke 2015-06-05 15:14:03

0

我不能让亚兰Dulyan代码工作在这个

for subform, data in zip(formset.forms, recipe_ingredients): 
    subform.initial = data 

显然对事情的Django 1.8改变了,我不能重复一个cached_property

形式 - django.utils.functional。在0x7efda9ef9080

cached_property对象,我得到这个错误

拉链参数#1必须支持迭代

但我还是拿字典,并直接分配到我的表单集和它的工作,我从这里的例子:

https://docs.djangoproject.com/en/dev/topics/forms/formsets/#understanding-the-managementform

from django.forms从myapp.forms导入formset_factory import ArticleForm

ArticleFormSet = formset_factory(ArticleForm, can_order=True) 
formset = ArticleFormSet(initial=[ 
    {'title': 'Article #1', 'pub_date': datetime.date(2008, 5, 10)}, 
    {'title': 'Article #2', 'pub_date': datetime.date(2008, 5, 11)}, 
]) 

我将代码分配成模板到模板

return self.render_to_response(
self.get_context_data(form=form, inputvalue_numeric_formset=my_formset(initial=formset_dict)