2010-02-04 7 views
9

django tiene incorporado este complejo ORM, pero después de pasar mucho tiempo en él, todavía me resulta difícil realizar consultas que son notablemente simples en SQL. Incluso hay algunas cosas simples que no puedo encontrar a través del django ORM (por ejemplo, 'select distinct column1 from tablename').django - ¿guía para ORM para usuarios de SQL?

¿Hay alguna documentación que muestre "Para las sentencias de SQL comunes, así es como se hace en django"?

(Yo probé Google principio, pero tampoco no es por ahí o simplemente no puedo pensar en la consulta derecha ...)

Respuesta

8

Hay algunas cosas que son ridículamente simples en SQL que son difíciles o imposibles a través de un ORM. Esto se llama "object-relational impedance mismatch". Esencialmente, un ORM trata cada fila en una base de datos como un objeto separado. Por lo tanto, las operaciones que implican tratar los valores por separado de su fila se vuelven bastante desafiantes. Las versiones recientes de Django (1.1+) mejore esta situación un tanto con aggregation support, pero para muchas cosas, solo SQL funcionará.

Para este fin, django ofrece varios métodos para dejarlo caer en sql sin procesar de forma bastante simple. Algunos de ellos devuelven objetos del modelo como resultados, mientras que otros lo llevan hasta su conector DBAPI2. El más bajo nivel es el siguiente:

from django.db import connection 

cursor = connection.cursor() 
cursor.execute("SELECT DISTINCT column1 FROM tablename") 
row = cursor.fetchone() 

Si desea devolver un conjunto de consultas de una consulta SQL, utilice la prima() en el gerente de su modelo:

qs = ModelName.objects.raw("""SELECT first_name 
           FROM myapp_modelname 
           WHERE last_name = 'van Rossum'") 
for person in qs: 
    print person.first_name # Result already available 
    print person.last_name # Has to hit the DB again 

Nota: prima () solo está disponible en la versión de desarrollo de Django, que debería fusionarse en trunk a partir de 1.2.

La información completa está disponible en la documentación bajo Performing raw SQL queries.

+0

Esto lo hizo por mí. El punto clave es que el ORM extrae un conjunto de objetos ("objeto" ~ = "fila completa"), pero una fila de resultados de SELECT DISTINCT no se puede conectar a un solo objeto. Entonces, si necesita objetos, use el ORM; si necesita un resultado donde una fila no se puede asignar de manera confiable a un solo objeto, use SQL directamente. Gracias. – sienkiew

4

Un buen punto de partida para hacer Django consultas es la documentación de Django sí mismos.

http://docs.djangoproject.com/en/dev/topics/db/queries/

Éstos son algunos ejemplos:

select * from table 
= 
ModelName.objects.all() 

filtrado:

select * from table where column = 'foo' 
= 
ModelName.objects.filter(column='foo') 

Específicamente con respecto al uso de distintos utiliza el método distinto() de un conjunto de consultas de Django.

Aquí está el enlace relevante en la documentación. http://docs.djangoproject.com/en/dev/ref/models/querysets/#distinct

Actualización: El ORM lo ayuda permitiéndole usar interacciones orientadas a objetos con sus datos. No escribe código que traduce el conjunto de resultados de su consulta en un conjunto de objetos. Lo hace automáticamente Ese es el cambio fundamental en el proceso de pensamiento que tienes que hacer.

Empiezas a pensar en términos de 'Tengo este objeto, necesito obtener todos los otros objetos que son como' Entonces puedes preguntarle al ORM por esos objetos. ORM, necesito todos los objetos de la clase de productos que tienen un atributo del color "azul" lenguaje ORM específica

de Django para que se:

products = Product.objects.filter(color='blue') 

Esto se hace en lugar de:

  • escribir su consulta SQL,
  • adecuadamente escapan todos los argumentos,
  • la conexión a la base de datos,
  • consultando la base de datos y manejando los errores de conexión/consulta,
  • obteniendo el conjunto de resultados,
  • iterando en el conjunto de resultados traduciendo los valores devueltos en objetos adecuados a los que puede llamar métodos.

Ese es el valor en el uso de un ORM. Simplificación de código y tiempo de desarrollo reducido.

+0

Por supuesto, leí la documentación antes de preguntar, aunque en el mundo moderno puedo entender por qué podría suponer lo contrario. Mi problema es que la documentación no responde a mis preguntas de manera muy efectiva. Nunca me pareció difícil entender RDBMS, y no está del todo claro cómo se supone que el ORM me está "ayudando". Tenía la esperanza de encontrar "Libro de frases para viajeros: Django para hablantes de SQL". – sienkiew

+0

Actualicé mi respuesta, espero que esto ayude a explicar más el proceso de pensamiento. – wlashell

6

Piénselo de esta manera.

"Para SQL hack-arounds comunes, ¿qué era lo orientado a objetos que se suponía que debía hacer en primer lugar?"

El problema no es que el ORM sea complejo. Es que su cerebro ha sido deformado en el molde de SQL, lo que hace que sea difícil ver los objetos con claridad.

reglas generales:

  • Si piensan que es un simple SELECT FROM WHERE, parar. Pregunte qué objetos necesita ver en el conjunto de resultados. Luego encuentra esos objetos y trabaja con el administrador de objetos.

  • Si crees que es un JOIN simple, detente. Pregunta qué objeto principal quieres. Recuerde, los objetos no usan claves foráneas. Unirse no significa nada. Un objeto parece romper 1NF y contiene un conjunto completo de objetos relacionados dentro de él. Luego encuentre los objetos "primarios" y trabaje con el administrador de objetos. Utilice las consultas de objetos relacionados para encontrar objetos relacionados.

  • Si crees que es un OUTER JOIN, detente. Pregunta qué dos cosas quieres ver en el conjunto de resultados. Una combinación externa es cosas que unirán a UNIONED con cosas que no se unirán. ¿Cuáles son las cosas en primer lugar? Luego encuentre los objetos "primarios" y trabaje con el administrador de objetos. Algunos tendrán conjuntos de objetos relacionados. Algunos no lo harán.

  • Si cree que es un WHERE EXISTS o WHERE IN con una subconsulta, su modelo probablemente esté incompleto. A veces, requiere una unión elegante. Pero si está haciendo este tipo de comprobación, generalmente significa que necesita una propiedad en su modelo.

  • Si cree que necesita SELECCIONAR DISTINCT, ha perdido el barco por completo. Eso es solo un conjunto de Python. Simplemente obtiene los valores de columna en un conjunto de Python. Esos son los valores distintivos.

  • Si crees que necesitas un GROUP BY, estás ignorando Python collections.defaultdict. Usar Python to para GROUP BY suele ser más rápido que preocuparse con SQL.

    Excepto para el almacenamiento de datos. Lo cual no deberías estar haciendo en Django. Debe usar SQLAlchemy para el almacenamiento de datos.

2

Para su específica de cómo hacerlo, usted lo haría así:

MyModel.objects.values_list('column1', flat=True).distinct() 

Pero otros carteles en lo correcto al decir que no debe estar pensando '¿cómo escribo esto en SQL el ORM '. Cuando aprendiste Python, proveniente de Java o C++ o lo que sea, pronto aprendiste a olvidarte de "cómo escribo este código Java en Python", y simplemente me concentré en resolver el problema usando Python. Lo mismo debería ser cierto de usar el ORM.

Cuestiones relacionadas