2010-07-19 39 views
6

He creado un formulario para guardar una receta. Hace uso de un formulario y un formset en línea. Tengo usuarios con archivos de texto que contienen recetas y les gustaría cortar y pegar los datos para facilitar la entrada. He resuelto cómo rellenar la parte del formulario después de procesar la entrada de texto sin formato, pero no puedo encontrar la manera de completar el formset en línea.Datos iniciales para Django Inline Formsets

Parece que la solución casi se explica aquí: http://code.djangoproject.com/ticket/12213 pero no puedo juntar las piezas.

Mis modelos:

#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 

Se crea el formulario de receta con un ModelForm:

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

Y el código correspondiente en la vista (las llamadas a analizar la forma se eliminan las entradas):

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

Con el FormSet() vacío como el anterior, puedo iniciar la página con éxito. He intentado algunas formas de alimentar el juego de formularios de la cantidad, unit_of_measure y los ingredientes que he identificado como:

  • datos de ajuste iniciales, pero que no funciona para juegos de formularios en línea
  • que pasan por un diccionario, pero que genera la gestión forman errores
  • jugado un poco con init, pero estoy un poco fuera de mi no

Cualquier sugerencia muy apreciados.

Respuesta

19

Mi primera sugerencia sería tomar la salida fácil: guardar los Recipe y RecipeIngredient s, a continuación, utilizar el Recipe resultante como su instancia al hacer la FormSet. Es posible que desee agregar un campo booleano "revisado" a sus recetas para indicar si el formulario fue aprobado por el usuario.

Sin embargo, si usted no quiere ir por ese camino por cualquier razón, usted debe ser capaz de llenar sus juegos de formularios de esta manera:

Vamos a suponer que usted ha analizado los datos de texto en ingredientes de la receta , y tienen una lista de diccionarios como ésta:

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

los números en los campos "unidad" "ingrediente" y son los valores de clave principal para los respectivos ingredientes y unidades de objetos de tipo indicador. Supongo que ya ha formulado alguna forma de emparejar el texto con los ingredientes en su base de datos, o crear otros nuevos.

entonces usted puede hacer:

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

Esto define la propiedad initial de cada forma en el juego de formularios a un diccionario de la lista de recipe_ingredients. Parece que me funciona en términos de mostrar el formset, pero aún no he intentado guardarlo.

+0

Gran consejo Aram, muchas gracias. Voy a probar las opciones hoy. Me gusta especialmente tener una opción fácil ... – Sinidex

+0

El uso de zip definitivamente funciona y puedo confirmar que también funciona guardar el formulario de la manera habitual. Todavía tengo que desarrollar la coincidencia del texto analizado con los ingredientes relevantes y el objeto de unidades de medida como usted señaló, pero creo que debería ser manejable. Gran solución – Sinidex

+1

Sí, sí y sí. ¡Esta es una gran solución! Me costó mucho alcanzar esto. Primero estaba buscando cómo construir cada formulario en el conjunto. Luego se dio cuenta de que el trabajo inicial * does * work, en una base de formulario (no formset). En zip confiamos en ™ – Flowpoke

0

no pude hacer que el código Aram Dulyan trabaja en este

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

parecer algo cambió en Django 1.8 que no puedo repetir una cached_property

formas - django.utils.functional. cached_property objeto en 0x7efda9ef9080

tengo este error

argumento postal # 1 debe apoyar iteración

Pero todavía tomar el diccionario y asignarlo directamente a mi juego de formularios y ha funcionado, i tomó el ejemplo de aquí:

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

django.forms de importación formset_factory de myapp.forms importar 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)}, 
]) 

Mi código en asignar formset a la plantilla

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