2009-02-05 4 views
5

J'ai quelques modèles en django qui sont connectés plusieurs-à-plusieurs. Je veux créer des instances de ces modèles dans la mémoire, les présenter à l'utilisateur (via des appels de méthode personnalisés à l'intérieur des view-templates) et si l'utilisateur est satisfait, enregistrez-les dans la base de données.Comment travailler avec des relations many-to-many non enregistrées dans django?

Cependant, si j'essaie de faire quelque chose sur les instances de modèle (méthodes de rendu d'appel, par exemple), j'obtiens un message d'erreur indiquant que je dois d'abord enregistrer les instances. La documentation dit que c'est parce que les modèles sont dans une relation plusieurs-à-plusieurs.

Comment présenter des objets à l'utilisateur et lui permettre de les sauvegarder ou de les supprimer sans encombrer ma base de données?

(je suppose que je pourrais désactiver les opérations de manutention et de moi-même les faire tout au long de l'ensemble du projet, mais cela ressemble à une mesure potentiellement sujette à l'erreur ...)

Thx!

Répondre

4

Je pense que l'utilisation de formulaires django peut être la réponse, comme indiqué dans la documentation this (recherche de m2m ...).

Sous la direction d'ajouter quelques explications pour d'autres personnes qui pourraient avoir le même problème:

que vous avez un modèle comme celui-ci:

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]) 

alors vous ne pouvez pas appeler unicode() sur un non enregistré objet Bar . Si vous ne voulez imprimer les choses avant qu'ils seront sauvés, vous devez faire:

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) 

Ainsi, dans ce cas, vous devez avoir sauvé des objets Foo (que vous pouvez valider avant d'enregistrer ceux-ci, à l'aide leur propre forme), et avant de sauvegarder les modèles avec de nombreuses touches, vous pouvez également les valider. Tout cela sans avoir besoin de sauvegarder les données trop tôt et de gâcher la base de données ou de traiter les transactions ...

6

Je voudrais ajouter un champ qui indique si les objets sont "brouillon" ou "en direct". De cette façon, ils sont persistants à travers les demandes, les sessions, etc. et django cesse de se plaindre.

Vous pouvez ensuite filtrer vos objets pour afficher uniquement les objets "en direct" dans les vues publiques et afficher uniquement les objets "brouillon" à l'utilisateur qui les a créés. Cela peut également être étendu pour autoriser les objets "archivés" (ou tout autre état qui a du sens).

0

Réponse très tardive, mais l'équipe de wagtail a créé une extension Django distincte appelée django-modelcluster. C'est ce qui alimente les avant-projets de leur CMS.

Il vous permet de faire quelque chose comme ça (de leur 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) 

Ensuite, les modèles peuvent être utilisés comme ceci:

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

Ici, ParentalKey est le remplacement de Django ForeignKey . De même, ils ont ParentalManyToManyField pour remplacer ManyToManyField de Django.

Questions connexes