Argument- und Elementnamen aus Variablen?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
Judge
User
Beiträge: 129
Registriert: Mittwoch 13. Juni 2012, 22:27
Wohnort: Ratingen
Kontaktdaten:

Hallo zusammen!

Ich habe eine Django-Applikation und bin beim Schreiben eines Management Commands auf eine meiner allgemeine Python-Wissenslücke gestoßen:

Ich suche einen Satz an Datenbankobjekten mit der `.filter` Methode von Django:

Code: Alles auswählen

cards = RfidCard.objects.filter(unavailable__exact=True)
`unavailable` ist in meinem Model ein `BooleanField`.

Soweit so gut; nun habe ich weitere `BooleanField`s in meinem Model, für die ich exakt dieselben Möglichkeiten darstellen will. Daher möchte ich gerne mit variablen arbeiten, statt irgendwelchem "if ..." und statischen Varianten.

Und hier beginnt mein Problem: Wie macht man denn das für Argumente und Elementnamen in Python?
Ich habe für Argumente einen ersten Erfolg mit folgender `eval`-Variante des vorigen Codes erzielt:

Code: Alles auswählen

cards = eval(f"RfidCard.objects.filter({flag}__exact=True)")
Hierdurch kann ich irgend einen Namen meiner BooleanFields (unavailable, placeholder, no_auto_complete) nutzen und bekomme das erwartete QuerySet als Ergebnis.

In den so ausgelesenen Model-Instanzen gibt es diese Felder aber dann ja als Property, welche ich gerne überschreiben würde. Zum Beispiel:

Code: Alles auswählen

for card in eval(f"RfidCard.objects.filter({flag}__exact=True)"):
    card.{flag} = False
Aber: Das geht ja so nicht. Ich komme auch mit keiner eval-Variante ans Ziel gerade ... ich habe das Gefühl, ich stehe da einfach heftig auf dem Schlauch; ich komme aber seit Tagen nicht drauf.

Hat jemand einen Tipp für mich?
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Code: Alles auswählen

#
# Das hier:
#
cards = RfidCard.objects.filter(unavailable__exact=True)
#
# Ist äquivalent zu dem hier:
#
cards = RfidCard.objects.filter(**{"unavailable__exact": True})
#
# Und da könnte man den Flag-Namen natürlich so einbauen:
#
cards = RfidCard.objects.filter(**{f"{flag}__exact": True})
Ich weiss allerdings nicht ob es vom Django-ORM nicht auch eine schönere Lösung gibt.

Und für das abfragen und setzen von Attributen über das Objekt und den Attributnamen, gibt es `getattr()` und `setattr()`.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
Judge
User
Beiträge: 129
Registriert: Mittwoch 13. Juni 2012, 22:27
Wohnort: Ratingen
Kontaktdaten:

Perfekt! Danke!
Antworten