Django Inline Formsets的初始数据 [英] Initial Data for Django Inline Formsets

查看:239
本文介绍了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 =真的)

class Meta:
order = ['title']

def __unicode __(self):
return self.title

def get_absolute_url(self):
return self.id

class食谱(models.Model):
title = models.CharField(max_length = 255)
description = models.TextField(blank = True)
directions = models.TextField()

class Meta:
order = ['title']

def __unicode __(self):
return self.id

def get_absolute_url )
return/ recipes /%s /%self.id

class UnitOfMeasure(models.Model):
title = models.CharField(max_length = 10,unique = true)

class Meta:
order = ['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)
ingredients = models.ForeignKey(Ingredient)
recipe = models.ForeignKey(Recipe)

def __unicode __自我):
return self.id

配方表单是使用ModelForm创建的: / p>

 类AddRecipeForm(ModelF orm):
class Meta:
model = Recipe
extra = 0

而视图中的相关代码(调用解析表单输入被删除):

  def raw_text )
如果request.method =='POST':

...

form_data = {'title':title,
'description ':description,
'directions':directions,
}

form = AddRecipeForm(form_data)

#count变量表示RecipeIngredients
FormSet = inlineformset_factory(Recipe,RecipeIngredient,
extra = count,can_delete = False)
formset = FormSet()

返回render_to_response('recipes / form_recipe.html ',{
'form':form,
'formset':formset,
})




返回render_to_response('recipes / form_raw_text.html',{})

如上所述,FormSet()为空,我可以成功启动该页面。我已经尝试了几种方式来填充表单数量,unit_of_measure和我已经确定的成分,包括:




  • 设置初始数据, t @ b $ b
  • 传递一个字典,但是会生成管理表单错误

  • 使用 init 播放,但是有点超出我的深度



任何建议非常感谢。

解决方案

我的第一个建议是采取简单的方法:保存配方 RecipeIngredient s,然后在生成 FormSet 时,使用生成的配方作为实例。您可能需要在配方中添加一个已评估布尔字段,以指示用户是否批准了表单。



但是,如果您不想您可以按照以下原则填写您的表单:



我们假设您将文本数据解析为配方成分,有一个这样的字典列表:

  recipe_ingredients = [
{
'成分':2 ,
'quantity':7,
'unit':1
},
{
'成分':3,
'quantity':5 ,
'unit':2
},
]

成分和单位字段中的数字是各成分和度量对象单位的主键值。我假设你已经制定了一些匹配文本到数据库中的成分,或者创建新数据库的方法。



然后,您可以执行以下操作:

  RecipeFormset = inlineformset_factory(
配方,
RecipeIngredient,
extra = len(recipe_ingredients),
can_delete = F $)
formset = RecipeFormset()

用于子表单,zip中的数据(formset.forms,recipe_ingredients):
subform.initial = data

返回render_to_response('recipes / form_recipe.html',{
'form':form,
'formset':formset,
})
/ pre>

这将将表单中每个表单的初始化属性设置为 recipe_ingredients 列表。在显示表单时,似乎对我来说,但我还没有尝试保存。


I have put together a form to save a recipe. It makes use of a form and an inline formset. I have users with text files containing recipes and they would like to cut and paste the data to make entry easier. I have worked out how to populate the form portion after processing the raw text input but I cannot figure out how to populate the inline formset.

It seems like the solution is almost spelled out here: http://code.djangoproject.com/ticket/12213 but I can't quite put the pieces together.

My models:

#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

The recipe form is created using a ModelForm:

class AddRecipeForm(ModelForm):
    class Meta:
        model = Recipe
        extra = 0

And the relevant code in the view (calls to parse out the form inputs are deleted):

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', {})

With the FormSet() empty as above I can successfully launch the page. I have tried a few ways to feed the formset the quantity, unit_of_measure and ingredients I have identified including:

  • setting initial data but that doesn't work for inline formsets
  • passing a dictionary, but that generates management form errors
  • played around with init but I'm a bit out of my depth there

Any suggestions greatly appreciated.

解决方案

My first suggestion would be to take the simple way out: save the Recipe and RecipeIngredients, then use the resulting Recipe as your instance when making the FormSet. You may want to add a "reviewed" boolean field to your recipes to indicate whether the formsets were then approved by the user.

However, if you don't want to go down that road for whatever reason, you should be able to populate your formsets like this:

We'll assume that you have parsed the text data into recipe ingredients, and have a list of dictionaries like this one:

recipe_ingredients = [
    {
        'ingredient': 2,
        'quantity': 7,
        'unit': 1
    },
    {
        'ingredient': 3,
        'quantity': 5,
        'unit': 2
    },
]

The numbers in the "ingredient" and "unit" fields are the primary key values for the respective ingredients and units of measure objects. I assume you have already formulated some way of matching the text to ingredients in your database, or creating new ones.

You can then do:

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,
     })

This sets the initial property of each form in the formset to a dictionary from your recipe_ingredients list. It seems to work for me in terms of displaying the formset, but I haven't tried saving yet.

这篇关于Django Inline Formsets的初始数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆