Dies wurde in Django 1.9 mit form_kwargs behoben .
Ich habe ein Django-Formular, das so aussieht:
class ServiceForm(forms.Form):
option = forms.ModelChoiceField(queryset=ServiceOption.objects.none())
rate = forms.DecimalField(widget=custom_widgets.SmallField())
units = forms.IntegerField(min_value=1, widget=custom_widgets.SmallField())
def __init__(self, *args, **kwargs):
affiliate = kwargs.pop('affiliate')
super(ServiceForm, self).__init__(*args, **kwargs)
self.fields["option"].queryset = ServiceOption.objects.filter(affiliate=affiliate)
Ich nenne dieses Formular so etwas:
form = ServiceForm(affiliate=request.affiliate)
Wo request.affiliate
ist der angemeldete Benutzer? Dies funktioniert wie vorgesehen.
Mein Problem ist, dass ich dieses einzelne Formular jetzt in ein Formularset verwandeln möchte. Was ich nicht herausfinden kann, ist, wie ich die Partnerinformationen beim Erstellen des Formularsatzes an die einzelnen Formulare weitergeben kann. Laut den Dokumenten muss ich so etwas tun, um daraus ein Formset zu machen:
ServiceFormSet = forms.formsets.formset_factory(ServiceForm, extra=3)
Und dann muss ich es so erstellen:
formset = ServiceFormSet()
Wie kann ich nun Affiliate = request.affiliate auf diese Weise an die einzelnen Formulare übergeben?
quelle
functools.partial
anstelle von Djangos zu verwendendjango.utils.functional.curry
. Sie tun dasselbe, außer dassfunctools.partial
anstelle einer regulären Python-Funktion ein bestimmter aufrufbarer Typ zurückgegeben wird und derpartial
Typ nicht als Instanzmethode gebunden wird, wodurch das Problem, dass dieser Kommentarthread hauptsächlich dem Debuggen gewidmet war, sauber gelöst wird.Offizieller Dokumentweg
Django 2.0:
https://docs.djangoproject.com/de/2.0/topics/forms/formsets/#passing-custom-parameters-to-formset-forms
quelle
Ich würde die Formularklasse dynamisch in einer Funktion erstellen, damit sie über das Schließen Zugriff auf den Partner hat:
Als Bonus müssen Sie das Abfrageset im Optionsfeld nicht neu schreiben. Der Nachteil ist, dass Unterklassen ein wenig funky sind. (Jede Unterklasse muss auf ähnliche Weise erstellt werden.)
bearbeiten:
Als Antwort auf einen Kommentar können Sie diese Funktion an jedem Ort aufrufen, an dem Sie den Klassennamen verwenden würden:
quelle
Das hat bei mir funktioniert, Django 1.7:
Hoffe es hilft jemandem, ich habe lange genug gebraucht, um es herauszufinden;)
quelle
staticmethod
hier gebraucht wird?Ich mag die Verschlusslösung, um "sauberer" und pythonischer zu sein (also +1 bis mmarshall Antwort), aber Django-Formulare haben auch einen Rückrufmechanismus, den Sie zum Filtern von Abfragesätzen in Formsätzen verwenden können.
Es ist auch nicht dokumentiert, was meiner Meinung nach ein Indikator ist, den die Django-Entwickler vielleicht nicht so sehr mögen.
Sie erstellen Ihr Formset also im Grunde gleich, fügen aber den Rückruf hinzu:
Dadurch wird eine Instanz einer Klasse erstellt, die folgendermaßen aussieht:
Dies sollte Ihnen die allgemeine Idee geben. Es ist etwas komplexer, den Rückruf zu einer Objektmethode wie dieser zu machen, bietet Ihnen jedoch etwas mehr Flexibilität als ein einfacher Funktionsrückruf.
quelle
Ich wollte dies als Kommentar zu Carl Meyers Antwort platzieren, aber da dies Punkte erfordert, habe ich es einfach hier platziert. Ich habe 2 Stunden gebraucht, um das herauszufinden, also hoffe ich, dass es jemandem hilft.
Ein Hinweis zur Verwendung der inlineformset_factory.
Ich habe diese Lösung selbst verwendet und sie hat perfekt funktioniert, bis ich sie mit der inlineformset_factory ausprobiert habe. Ich habe Django 1.0.2 ausgeführt und eine seltsame KeyError-Ausnahme erhalten. Ich habe auf den neuesten Kofferraum aktualisiert und es hat direkt funktioniert.
Ich kann es jetzt ähnlich verwenden:
quelle
modelformset_factory
. Danke für diese Antwort!Ab Commit e091c18f50266097f648efc7cac2503968e9d217 am Di Aug 14 23:44:46 2012 +0200 kann die akzeptierte Lösung nicht mehr funktionieren.
Die aktuelle Version der Funktion django.forms.models.modelform_factory () verwendet eine "Typkonstruktionstechnik", die die Funktion type () für das übergebene Formular aufruft, um den Metaklassentyp abzurufen, und dann das Ergebnis verwendet, um ein Klassenobjekt von ihm zu erstellen Tippe on the fly ::
Dies bedeutet, dass sogar ein
curry
Ed oderpartial
Objekt, das anstelle eines Formulars übergeben wurde, sozusagen "die Ente dazu bringt, Sie zu beißen": Es ruft eine Funktion mit den Konstruktionsparametern einesModelFormClass
Objekts auf und gibt die Fehlermeldung zurück ::Um dies zu umgehen, habe ich eine Generatorfunktion geschrieben, die einen Abschluss verwendet, um eine Unterklasse einer als ersten Parameter angegebenen Klasse zurückzugeben, die dann
super.__init__
nachupdate
dem kwargs mit denjenigen aufgerufen wird, die beim Aufruf der Generatorfunktion angegeben wurden ::Dann rufen Sie in Ihrem Code die Formularfactory als :: auf
Vorbehalte:
quelle
Die Lösung von Carl Meyer sieht sehr elegant aus. Ich habe versucht, es für modelformsets zu implementieren. Ich hatte den Eindruck, dass ich keine statischen Methoden innerhalb einer Klasse aufrufen konnte, aber Folgendes funktioniert unerklärlicherweise:
Meiner Ansicht nach, wenn ich so etwas mache:
Dann wird das Schlüsselwort "request" an alle Mitgliedsformulare meines Formularsatzes weitergegeben. Ich bin zufrieden, aber ich habe keine Ahnung, warum das funktioniert - es scheint falsch. Irgendwelche Vorschläge?
quelle
MyFormSet.form.Meta.model
.MyFormSet.form().Meta.model
. Wirklich offensichtlich.Ich habe einige Zeit damit verbracht, dieses Problem herauszufinden, bevor ich diesen Beitrag gesehen habe.
Die Lösung, die ich gefunden habe, war die Verschlusslösung (und diese Lösung habe ich zuvor mit Django-Modellformularen verwendet).
Ich habe die oben beschriebene curry () -Methode ausprobiert, konnte sie jedoch mit Django 1.0 nicht zum Laufen bringen, sodass ich am Ende zur Closure-Methode zurückkehrte.
Die Schließmethode ist sehr ordentlich und die einzige kleine Seltsamkeit besteht darin, dass die Klassendefinition in der Ansicht oder einer anderen Funktion verschachtelt ist. Ich denke, die Tatsache, dass dies für mich seltsam aussieht, ist ein Hangup aus meiner vorherigen Programmiererfahrung und ich denke, jemand mit einem Hintergrund in dynamischeren Sprachen würde kein Augenlid schlagen!
quelle
Ich musste etwas Ähnliches tun. Dies ähnelt der
curry
Lösung:quelle
Aufgrund dieser Antwort fand ich eine klarere Lösung:
Und laufen Sie es in Sichtweite wie
quelle
Ich bin ein Neuling hier, daher kann ich keinen Kommentar hinzufügen. Ich hoffe, dass dieser Code auch funktioniert:
zum Hinzufügen zusätzlicher Parameter zu den Formularsätzen
BaseFormSet
anstelle von Formularen.quelle