2009-02-05 9 views
5

Ho un paio di modelli in django che sono collegati molti a molti. Voglio creare istanze di questi modelli nella memoria, presentarli all'utente (tramite metodo personalizzato-chiama all'interno dei modelli di visualizzazione) e, se l'utente è soddisfatto, salvarli nel database.Come lavorare con relazioni molti-a-molti non salvate in django?

Tuttavia, se provo a fare qualcosa sulle istanze di modello (chiama metodi di rendering, ad es.), Ricevo un messaggio di errore che dice che prima devo salvare le istanze. La documentazione dice che questo è perché i modelli sono in una relazione molti-a-molti.

Come presentare all'utente oggetti e consentirgli di salvarli o eliminarli senza ingombrare il mio database?

(Credo che avrei potuto spegnere le operazioni di manipolazione e di fare io stesso durante l'intero progetto, ma questo suona come una misura potenzialmente soggetto a errori ...)

Thx!

risposta

4

Penso che l'uso di moduli django possa essere la risposta, come indicato nella documentazione this (ricerca di m2m ...).

A cura di aggiungere qualche spiegazione per le altre persone che potrebbero avere lo stesso problema:

dire di avere un modello come questo:

from django.db import models 
from django.forms import ModelForm 

class Foo(models.Model): 
    name = models.CharField(max_length = 30) 

class Bar(models.Model): 
     foos = models.ManyToManyField(Foo) 

    def __unicode__(self): 
     return " ".join([x.name for x in foos]) 

allora non si può chiamare unicode() su un oggetto Bar non salvato . Se si desidera stampare le cose fuori prima che saranno salvati, si deve fare questo:

class BarForm(ModelForm): 
    class Meta: 
     model = Bar 

def example():  
    f1 = Foo(name = 'sue') 
    f1.save() 
    f2 = foo(name = 'wendy') 
    f2.save() 
    bf = BarForm({'foos' : [f1.id, f2.id]}) 
    b = bf.save(commit = false) 
    # unfortunately, unicode(b) doesn't work before it is saved properly, 
    # so we need to do it this way: 
    if(not bf.is_valid()): 
     print bf.errors 
    else: 
     for (key, value) in bf.cleaned_data.items(): 
      print key + " => " + str(value) 

Quindi, in questo caso, è necessario aver salvato oggetti Foo (che si potrebbe convalidare prima di salvare coloro che, utilizzando la propria forma), e prima di salvare i modelli con molti a molti tasti, è possibile convalidare anche quelli. Tutto senza la necessità di salvare i dati troppo presto e rovinare il database o gestire transazioni ...

6

Vorrei aggiungere un campo che indica se gli oggetti sono "bozza" o "live". In questo modo sono persistenti attraverso richieste, sessioni, ecc. E Django smette di lamentarsi.

È quindi possibile filtrare gli oggetti per mostrare solo oggetti "in diretta" nelle viste pubbliche e mostrare solo oggetti "bozza" all'utente che li ha creati. Questo può anche essere esteso per consentire oggetti "archiviati" (o qualsiasi altro stato che abbia senso).

0

Risposta molto tarda, ma il team di Wagtail ha creato un'estensione Django separata denominata django-modelcluster. È ciò che alimenta le anteprime delle bozze del loro CMS.

Esso permette di fare qualcosa di simile (dal loro README):

from modelcluster.models import ClusterableModel 
from modelcluster.fields import ParentalKey 

class Band(ClusterableModel): 
    name = models.CharField(max_length=255) 

class BandMember(models.Model): 
    band = ParentalKey('Band', related_name='members') 
    name = models.CharField(max_length=255) 

Poi i modelli possono essere utilizzati in questo modo:

beatles = Band(name='The Beatles') 
beatles.members = [ 
    BandMember(name='John Lennon'), 
    BandMember(name='Paul McCartney'), 
] 

Qui, ParentalKey è la sostituzione per Django di ForeignKey . Allo stesso modo, hanno ParentalManyToManyField per sostituire il ManyToManyField di Django.