2010-02-17 15 views
9

Digamos que tengo dos Django modelos de persona y de la compañía de la siguiente manera: -Django ForeignKey con nula = True, combinación interna y externa izquierda

class Company(models.Model): 
    name = models.CharField() 

class Person(models.Model): 
    last_name = models.CharField(blank=True) 
    first_name = models.CharField() 
    company = models.ForeignKey(Company, null=True, blank=True) 

Una persona puede o no pertenecer a una empresa.

Estoy usando MySQL. Quiero todas las Personas que no pertenecen a ninguna Compañía, es decir, Personas donde la compañía es nula.

Si hago Person.objects.filter(company__isnull=True) me sale un SQL que es esencialmente: -

SELECT * FROM PersonTable LEFT OUTER JOIN AgencyTable ON (PersonTable.company_id = AgencyTable.id) WHERE AgencyTable.id IS NULL

¿Cómo hago para lograr el SQL siguiente: -

SELECT * FROM PersonTable INNER JOIN AgencyTable ON (PersonTable.company_id = AgencyTable.id) WHERE AgencyTable.id IS NULL

Por lo que sé al leer la lista de correo de los usuarios de Django, este solía ser el comportamiento antes de QuerySet Refactor.

EDITAR - ¡Ahora veo la blasfemia de mi pregunta!

Lo que quiero decir es simplemente quiero hacer

SELECT * FROM PersonTable WHERE PersonTable.company_id IS NULL

+0

Bueno, si esto no es hacer sentido para ti, esto es en realidad una consulta 'base' que obtiene INTERIOR unido a otras consultas, y esto lleva a la extraña resultados repetitivos. – chefsmart

+0

Esta pregunta es realmente el resultado de un bloqueo mental. – chefsmart

Respuesta

1

Debe ser tan simple como:

Person.objects.filter(company_id__isnull=True) 

Nota el uso de company_id que es el campo entero predeterminado creado por el ForeignKey

Editar

Lo sentimos, no he usado activamente django desde 0.9.5. O estoy pensando en el comportamiento previo a la versión 1.0, o estoy confundiendo sqlalchemy y Django ORM. En cualquier caso, como dicen los comentarios, lo anterior parece no funcionar.

Parece que la única forma de obtener la consulta que desea en django actual es usar el parámetro de consulta .extra, que viene con una lista completa de advertencias.

Person.objects.extra(where=['company_id IS NULL']) 

Tenga en cuenta que esto puede no ser portátiles a todos DB de, y puede que no funcione en combinación con filtro(), y cualquier número de temas posibles. Yo recomendaría no usar esto a través de su código, y en lugar de moverlo a un classmethod en persona como:

@classmethod 
def list_unaffiliated_people(cls): 
    return cls.objects.extra(where=['company_id IS NULL']) 

Alternativamente, sólo tiene que utilizar la sintaxis correcta consulta ORM y absorber el golpe rendimiento posible (¿ha hecho la referencia de los consulta más complicado de ver es que sea más lento)

+0

Lo probé en el shell, me da FieldError: no se puede resolver la palabra clave 'company_id' en el campo. Las opciones son: company, first_name, last_name – chefsmart

+0

Hrm. Pensé que era posible consultar la clave de esa manera. Supongo que vuelve a la mesa de dibujo en ese caso. – Crast

+0

Eso no es posible. 'company__id__isnull' sería válido, pero generaría prácticamente el mismo SQL. – ayaz

0

Django tratar NULL como None objeto de Python así:?

Person.objects.filter(company = None) 
+0

Esto también da el mismo SQL. Supongo que la forma en que Django lo está haciendo no es tan mala después de todo. Me centraré en cómo puedo mejorar mis otras búsquedas y ver si puedo resolver mi problema. – chefsmart

14

Bueno, esta pregunta es viejo, y pronto el parche estará en Django.Sin embargo, durante el breve Mientras tanto, la respuesta está en http://code.djangoproject.com/ticket/10790:

Workaround: Instead of

Person.objects.filter(company=None)

use

Person.objects.exclude(company__isnull=False)

Cuestiones relacionadas