Domanda

Ho un modello come questo:

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

Ho una funzione a cui viene passato un elenco di filtri in cui ciascun filtro ha la forma {'tipo': qualcosa, 'valore': x}. Questa funzione deve restituire un insieme di risultati ANDing tutti i filtri insieme:

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

Ogni Subthing ha una proprietà booleana 'principale'. Ogni cosa ha 1 e solo 1 sottotitolo dove main == True.

Ora devo aggiungere un filtro che restituisca tutte le cose che hanno un Subthing dove main == True e subproperty == filter ['value']

Posso farlo come parte dell'oggetto Q che sto costruendo? Se no come altro? Il queryset che ottengo prima che il mio nuovo filtro possa essere abbastanza grande, quindi vorrei un metodo che non implichi il loop dei risultati.

È stato utile?

Soluzione

È un po 'più facile da capire se dai esplicitamente ai sottotitoli un " nome_relativo " nella loro relazione con la Cosa

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

Ora usi Django join sintassi per creare il tuo oggetto Q:

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

La relazione inversa ha il nome predefinito 'subthing_set', ma trovo che sia più facile seguirla se le dai un nome migliore come 'subthings'.

Altri suggerimenti

Uso (anziché final_q = Q () all'inizio)

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)

dovrebbe darti quello che vuoi, puoi anche regolare il tuo ciclo per creare l'elenco dei sub_vals e applicarlo dopo il ciclo.

subthing_set viene aggiunto automaticamente al campo relativo aggiunto alla Cosa per accedere ai Sottotitoli correlati.

puoi assegnare un altro nome correlato, ad esempio

thing=models.ForeignKey(Thing,related_name='subthings')
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top