[python] Was sind die Schritte, um ein ModelForm mit einer ManyToMany-Beziehung mit einem intermediären Modell in Django zu arbeiten?



1 Answers

Wenn du jetzt die Speichermethode verwendest, wird Django versuchen, mit dem Manager zu speichern (was Django nicht erlaubt). Leider ist das Verhalten, das Sie wollen, ein wenig komplizierter als das, was ModelForm standardmäßig tut. Was Sie tun müssen, ist ein Formularsatz erstellen.

Zuallererst müssen Sie die Optionen Ihrer ClientForm damit das Attribut groupes nicht angezeigt wird.

class ClientForm(ModelForm):
    class Meta:
        model = Client
        exclude = ('groupes',)

Als Nächstes müssen Sie die Ansicht ändern, um das Formset anzuzeigen:

from django.forms.models import inlineformset_factory

def modifier(request, id):
    client = Client.objects.get(id=id)    
    form = ClientForm(instance = client)
    # Create the formset class
    GroupeFormset = inlineformset_factory(Client, Groupe)
    # Create the formset
    formset = GroupeFormset(instance = client)

    dict = {
        "form": form
        , "formset" : formset
        , "instance" : client
    }

    if request.method == "POST":
        form = ClientForm(request.POST, instance = client)
        formset = GroupeFormset(request.POST, instance = client)

        if form.is_valid() and formset.is_valid():
            client_mod = form.save()
            formset.save()

            id = client_mod.id
            return HttpResponseRedirect(
                "/client/%(id)s/?err=success" % {"id" : id}
            )
        else:
            return HttpResponseRedirect(
                "/client/%(id)s/?err=warning" % {"id" : id}
            )

    return render_to_response(
        "client/modifier.html"
        , dict
        , context_instance=RequestContext(request)
    )

Und natürlich müssen Sie auch Ihre Vorlage optimieren, um das Formset zu rendern.

Weitere Informationen zu Formsets finden Sie in folgenden Artikeln:

Modellformsätze
Formsets

Question
  • Ich habe ein Client- und Groupe- Modell.
  • Ein Client kann Teil mehrerer Gruppen sein .
  • Kunden , die Teil einer Gruppe sind, können den kostenlosen Mietpreis ihrer Gruppe jederzeit aber nur einmal nutzen. Hier kommt das Zwischenmodell ( ClientGroupe ) mit diesen zusätzlichen Daten ins Spiel .

Für den Moment, wenn ich versuche, die m2m-Daten zu speichern, stirbt es einfach und sagt, ich sollte den ClientGroupe-Manager verwenden ... Was fehlt also?

Hier sind meine Modelle:

class Groupe(models.Model):
    nom = models.CharField(max_length=1500, blank=True)

class Client(models.Model):
    nom = models.CharField(max_length=450, blank=True)
    prenom = models.CharField(max_length=450, blank=True)
    groupes = models.ManyToManyField(Groupe, null = True, blank = True, through='ClientGroupe')

class ClientGroupe(models.Model):
    client = models.ForeignKey(Client)
    groupe = models.ForeignKey(Groupe)
    dt = models.DateField(null=True, blank=True) # the date the client is using its group's free rental rate    

    class Meta:
        db_table = u'clients_groupes'

und hier ist meine Ansicht:

def modifier(request, id):
    client = Client.objects.get(id=id)    
    form = ClientForm(instance = client)

    dict = {
        "form": form
        , "instance" : client
    }

    if request.method == "POST":
        form = ClientForm(request.POST, instance = client)

        if form.is_valid():
            client_mod = form.save()

            id = client_mod.id
            return HttpResponseRedirect(
                "/client/%(id)s/?err=success" % {"id" : id}
            )
        else:
            return HttpResponseRedirect(
                "/client/%(id)s/?err=warning" % {"id" : id}
            )

    return render_to_response(
        "client/modifier.html"
        , dict
        , context_instance=RequestContext(request)
    )

EDIT :

und hier ist der ClientForm-Code:

class ClientForm(ModelForm):
    class Meta:
        model = Client

EDIT # 2 : Hier ist die Fehlermeldung:

AttributeError at /client/445/

Cannot set values on a ManyToManyField which specifies an intermediary model. Use ClientGroupe's Manager instead.

Request Method:     POST
Request URL:    http://localhost/client/445/
Exception Type:     AttributeError
Exception Value:    Cannot set values on a ManyToManyField which specifies an intermediary model.  Use ClientGroupe's Manager instead.

Exception Location:     C:\Python25\lib\site-packages\django\db\models\fields\related.py  in __set__, line 574
Python Executable:  C:\xampp\apache\bin\apache.exe
Python Version:     2.5.2



Wenn Sie Ihr Formular speichern, speichern Sie das Client-Objekt. Wenn Sie nun einen Client der Gruppe zuweisen möchten, sollten Sie Folgendes tun:

clientgroupe = ClientGroupe.objects.create(client=client_instance, groupe=groupe_instance, dt=datetime.datetime.now())

wo client_instance und groupe_instance Ihre Client- und Groupe-Objekte.






Related