2010-07-19 9 views
6

Ho messo insieme un modulo per salvare una ricetta. Usa un modulo e un formset in linea. Ho utenti con file di testo contenenti ricette e vorrebbero tagliare e incollare i dati per facilitare l'accesso. Ho elaborato come compilare la parte del modulo dopo aver elaborato l'input di testo non elaborato, ma non riesco a capire come popolare il formset in linea.Formati iniziali per i moduli in linea Django

Sembra che la soluzione sia quasi specificata qui: http://code.djangoproject.com/ticket/12213 ma non riesco a mettere insieme i pezzi.

I miei modelli:

#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 

La forma ricetta viene creata usando un ModelForm:

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

E il relativo codice nella visualizzazione (chiamate per analizzare il modulo ingressi vengono cancellati):

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 FormSet() vuoto come sopra, posso avviare correttamente la pagina. Ho provato un paio di modi per alimentare il formset la quantità, unit_of_measure e gli ingredienti ho identificato tra cui:

  • i dati di impostazione iniziale, ma che non funziona per formsets linea
  • il superamento di un dizionario, ma che genera la gestione errori di forma
  • giocato in giro con init ma io sono un po 'fuori dalla mia profondità ci

Tutti i suggerimenti molto apprezzato.

risposta

19

Il mio primo suggerimento sarebbe quello di prendere la via più semplice out: salvare le Recipe e RecipeIngredient s, quindi utilizzare il risultante Recipe come l'istanza al momento della FormSet. Potresti voler aggiungere un campo booleano "revisionato" alle tue ricette per indicare se i formet sono stati approvati dall'utente.

Tuttavia, se non si vuole andare su questa strada per qualsiasi motivo, si dovrebbe essere in grado di popolare il formsets come questo:

Supponiamo che avete analizzato i dati di testo in ingredienti della ricetta , e hanno un elenco di dizionari come questo:

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

i numeri nella "ingrediente" e campi "unità abitativa" sono i valori di chiave primaria per i rispettivi ingredienti e le unità di oggetti indicatore. Presumo che tu abbia già formulato un modo per abbinare il testo agli ingredienti nel tuo database, o crearne di nuovi.

È quindi possibile fare:

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

Questa imposta la proprietà initial di ogni forma nel formset a un dizionario dall'elenco recipe_ingredients. Sembra funzionare per me in termini di visualizzazione del formset, ma non ho ancora provato a salvare.

+0

Ottimo consiglio Aram, grazie mille. Proverò le opzioni oggi. Mi piace soprattutto avere un'opzione facile ... – Sinidex

+0

L'utilizzo di zip funziona sicuramente e posso confermare che anche il salvataggio del modulo nel solito modo funziona. Ho ancora bisogno di costruire il matching del testo analizzato con gli ingredienti rilevanti e l'unità di misura oggetto come hai sottolineato, ma penso che dovrebbe essere gestibile. Ottima soluzione. – Sinidex

+1

Sì sì e sì. Questa è un'ottima soluzione! Ho avuto difficoltà a raggiungere questo. Prima stavo cercando come costruire ogni modulo nel set. Quindi, l'iniziale * realizzato * funziona, su una base di forma (non formata). In zip ci fidiamo di – Flowpoke

0

non ho potuto rendere il codice Aram Dulyan lavora su questo

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

A quanto pare qualcosa è cambiato in Django 1.8 che non riesco a scorrere un cached_property

forme - django.utils.functional. oggetto cached_property a 0x7efda9ef9080

ho ottenuto questo errore

argomento zip # 1 deve supportare l'iterazione

ma ho ancora prendere il dizionario e assegnarlo direttamente al mio formset e ha funzionato, ho preso l'esempio da qui:

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

da django.forms importare formset_factory da myapp.forms importare 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)}, 
]) 

Il mio codice su assegna formset a modello

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