Frage

Ich habe ein Modell wie diese bekommen:

class Thing(models.Model):
    property1 = models.IntegerField()
    property2 = models.IntegerField()
    property3 = models.IntegerField()

class Subthing(models.Model):
    subproperty = models.IntegerField()
    thing = modelsForeignkey(Thing)
    main = models.BooleanField()

Ich habe eine Funktion habe, die eine Liste von Filtern geleitet wird, wo jeder Filter der Form ist { ‚Typ‘: etwas, ‚Wert‘: x}. Diese Funktion benötigt eine Reihe von Ergebnissen zurückzukehren ANDing alle Filter zusammen:

final_q = Q()
for filter in filters:
        q = None
        if filter['type'] =='thing-property1':
            q = Q(property1=filter['value'])
        elif filter['type'] =='thing-property2':
            q = Q(property2=filter['value'])
        elif filter['type'] =='thing-property2':
            q = Q(property3=filter['value'])
        if q:
            final_q = final_q & q
return Thing.objects.filter(final_q).distinct()

Jeder Subthing hat eine Boolesche Eigenschaft 'main'. Jedes Ding hat 1 und nur 1 Subthing wo Haupt == True fest.

Ich brauche jetzt Filter hinzufügen, die alle Sachen gibt, die eine Subthing haben, wo main==True und subproperty==filter['value']

Kann ich das als Teil des Q Objekt Ich bin konstruieren? Wenn nicht, wie sonst? Die queryset ich vor meinem neuen Filter bekommen kann ziemlich groß sein, damit ich eine Methode möchte, die nicht über die Ergebnisse looping beinhaltet.

War es hilfreich?

Lösung

Es ist ein bisschen leichter zu verstehen, wenn Sie ausdrücklich Ihr Subthings eine „related_name“ in ihrer Beziehung zur Sache geben

class Subthing(models.Model):
    ...
    thing = models.ForeignKey(Thing, related_name='subthings')
    ...

Jetzt verwenden Sie Django beitreten Syntax Ihr Q-Objekt zu erstellen:

Q(subthings__main=True) & Q(subthings__subproperty=filter['value'])

Die umgekehrte Beziehung hat den Standardnamen ‚subthing_set‘, aber ich finde, dass es einfacher ist, zu folgen, wenn Sie ihm einen besseren Namen wie ‚subthings‘ geben.

Andere Tipps

Mit (statt final_q=Q() am Anfang)

final_q=Q(subthing_set__main=True)
sub_vals = map(lambda v: v['value'], filters)
if sub_vals:
    final_q = final_q & Q(subthing_set__subproperty__in=sub_vals)

sollten Sie bekommen, was Sie wollen, können Sie auch Ihre Schleife anpassen, um die sub_vals Liste zu erstellen und sie nach der Schleife anwenden.

subthing_set ist und automatisch hinzugefügt verwandter Bereich zum Dinge hinzugefügt zu verwandten Subthings zuzugreifen.

können Sie einen anderen verwandten Namen zuweisen, z.

thing=models.ForeignKey(Thing,related_name='subthings')
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top