2010-07-25 24 views
6

¿Es posible agregar una condición adicional para unirse a la declaración creada por django ORM?condiciones adicionales en join en django

Lo que necesito en SQL es

'SELECT "post"."id", COUNT("watchlist"."id") FROM "post" 
LEFT OUTER JOIN "watchlist" 
    ON ("post"."id" = "watchlist"."post_id" AND "watchlist"."user_id" = 1) 
WHERE "post"."id" = 123 GROUP BY … 

En Django mayoría de esto es

Post.objects.annotate(Count('watchinglist')).get(pk=123) 

Pero ¿cómo se puede añadir que AND "watchlist"."user_id" = … en condición de unión con el ORM de Django?

Al agregarlo al filtro no se pueden obtener objetos Post sin objetos asociados en la lista de seguimiento.

Respuesta

0
Post.objects.annotate(Count('watchinglist')).filter(pk=123).extra(where=['"watchlist"."user_id" = 1']) 

Happy Coding.

+2

parece que hace acually lo mismo que el filtro(). P.ej. agregando un parámetro a DONDE, no a ENCENDIDO, y, por lo tanto, proporcionando resultado vacío si no hay un objeto de lista de observación. – HoverHell

+0

Pero, en realidad, buena idea. Me perdí el parámetro 'extra' de Count. Parece que eso funciona. – HoverHell

+0

... o tal vez no. 'extra' parece tener un propósito algo diferente. – HoverHell

2

Respuesta breve: bajo ciertas condiciones - sí.

cuando se deja de construcción se une a GenericForeignKey, Django llama GenericRelation.get_extra_restriction que añade condición adicional a la cláusula ON con restricción "content_type_id".

Para "ForeignKey", este método también se llama mediante return None.

Puede usar este lugar para poner restricciones adicionales en la cláusula ON, si logra organizar su código para obtener los parámetros de restricción adecuados en determinado momento.

class UserForeignKey(models.ForeignKey): 

    def get_extra_restriction(self, where_class, alias, related_alias): 
     field = self.model._meta.get_field('user') 
     cond = where_class() 
     # Here is a hack to get custom condition parameters 
     value = SomeContextManager.get_needed_value() 

     lookup = field.get_lookup('exact')(field.get_col(related_alias), value) 
     cond.add(lookup, 'AND') 
     return cond 

class WatchList(models.Model): 

    user = UserForeignKey(User) 
+0

Salvaste mi vida hombre :) –

0

En uso v2.0 Django FilteredRelation

Post.objects.annotate(
    t=FilteredRelation(
     'watchlist', condition=Q(watchlist__user_id=1) 
).filter(t__field__in=...) 
Cuestiones relacionadas