Pregunta

Tengo un modelo como este:

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

Tengo una función a la que se le pasa una lista de filtros donde cada filtro tiene la forma {'tipo': algo, 'valor': x}. Esta función necesita devolver un conjunto de resultados Y unir todos los filtros:

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

Cada Subthing tiene una propiedad booleana 'main'. Cada Cosa tiene 1 y solo 1 Subthing donde main == True.

Ahora necesito agregar un filtro que devuelva todas las Cosas que tienen un Subthing donde main == True y subproperty == filter ['value']

¿Puedo hacer esto como parte del objeto Q que estoy construyendo? Si no, ¿de qué otra manera? El conjunto de consultas que obtengo antes de mi nuevo filtro puede ser bastante grande, por lo que me gustaría un método que no implique bucle sobre los resultados.

¿Fue útil?

Solución

Es un poco más fácil de entender si explícitamente le das a tus Subthings un " related_name " en su relación con la Cosa

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

Ahora, usa Únete a Django sintaxis para construir su objeto Q:

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

La relación inversa tiene el nombre predeterminado 'subthing_set', pero creo que es más fácil de seguir si le da un nombre mejor como 'subthings'.

Otros consejos

Uso (en lugar de final_q = Q () al principio)

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)

debería darte lo que quieres, también puedes ajustar tu ciclo para construir la lista de sub_valos y aplicarlo después del ciclo.

subthing_set es y se agrega automáticamente el campo relacionado agregado a la Cosa para acceder a Subthings relacionados.

puede asignar otro nombre relacionado, por ejemplo,

thing=models.ForeignKey(Thing,related_name='subthings')
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top