Estoy diseñando una base de datos bastante compleja y sé que algunas de mis consultas quedarán fuera del alcance del ORM de Django. ¿Alguien ha integrado SP con el ORM de Django con éxito? Si es así, ¿qué RDBMS y cómo lo hiciste?Cuál es la mejor manera de acceder a los procedimientos almacenados en ORM de Django
Respuesta
Nosotros (musicpictures.com/eviscape.com) escribimos ese fragmento de django pero no es toda la historia (de hecho, ese código solo fue probado en Oracle en ese momento).
Los procedimientos almacenados tienen sentido cuando se quiere reutilizar código SP probado y probado o cuando una llamada SP será más rápida que múltiples llamadas a la base de datos o donde la seguridad requiere acceso moderado a la base de datos o donde las consultas son muy complicadas/multipaso Estamos utilizando un enfoque de modelo híbrido/SP frente a las bases de datos Oracle y Postgres.
El truco está en hacer que sea fácil de usar y mantenerlo como "django". Utilizamos una función make_instance que toma el resultado del cursor y crea instancias de un modelo poblado por el cursor. Esto es bueno porque el cursor puede devolver campos adicionales. Entonces puede usar esas instancias en su código/plantillas al igual que los objetos normales del modelo django.
def make_instance(instance, values):
'''
Copied from eviscape.com
generates an instance for dict data coming from an sp
expects:
instance - empty instance of the model to generate
values - dictionary from a stored procedure with keys that are named like the
model's attributes
use like:
evis = InstanceGenerator(Evis(), evis_dict_from_SP)
>>> make_instance(Evis(), {'evi_id': '007', 'evi_subject': 'J. Bond, Architect'})
<Evis: J. Bond, Architect>
'''
attributes = filter(lambda x: not x.startswith('_'), instance.__dict__.keys())
for a in attributes:
try:
# field names from oracle sp are UPPER CASE
# we want to put PIC_ID in pic_id etc.
setattr(instance, a, values[a.upper()])
del values[a.upper()]
except:
pass
#add any values that are not in the model as well
for v in values.keys():
setattr(instance, v, values[v])
#print 'setting %s to %s' % (v, values[v])
return instance
# utilizar de esta manera:
pictures = [make_instance(Pictures(), item) for item in picture_dict]
# Y aquí están algunas funciones auxiliares:
def call_an_sp(self, var):
cursor = connection.cursor()
cursor.callproc("fn_sp_name", (var,))
return self.fn_generic(cursor)
def fn_generic(self, cursor):
msg = cursor.fetchone()[0]
cursor.execute('FETCH ALL IN "%s"' % msg)
thing = create_dict_from_cursor(cursor)
cursor.close()
return thing
def create_dict_from_cursor(cursor):
rows = cursor.fetchall()
# DEBUG settings (used to) affect what gets returned.
if DEBUG:
desc = [item[0] for item in cursor.cursor.description]
else:
desc = [item[0] for item in cursor.description]
return [dict(zip(desc, item)) for item in rows]
aplausos, Simon.
¿Por qué cierra el cursor en 'fn_generic'? –
Trabajo en un sistema inmenso con una base de datos a la que acceden múltiples aplicaciones, algunas C++, algunas python, algunas perl, algunas php, algunas basadas en web, muchas no. Me encanta cuando la lógica comercial está en los SP porque significa que la lógica es consistente en todas las implementaciones, y en nuestro caso al menos, hace que el mantenimiento sea mucho más fácil. –
he encontrado este comentario por russ magee: "Hemos evitado específicamente agregar características obvias similares a SQL a ORM de Django, porque al final del día, no estamos tratando de reemplazar SQL - solo estamos tratando de proporciona una forma conveniente de expresar consultas simples. Se espera que recurras simplemente a SQL sin formato para casos complejos ". –
usted tiene que utilizar la Utilidad de conexión en Django:
from django.db import connection
cursor = connection.cursor()
cursor.execute("SQL STATEMENT CAN BE ANYTHING")
entonces se puede recuperar los datos:
cursor.fetchone()
o:
cursor.fetchall()
Más información aquí: http://docs.djangoproject.com/en/dev/topics/db/sql/
Si desea ver un proyecto en ejecución real que utiliza SP, consulte minibooks. Una buena cantidad de SQL personalizado y utiliza Postgres pl/pgsql para SP. Creo que van a eliminar el SP eventualmente (justificación en trac ticket 92).
No.
En serio.
Mueva la lógica del procedimiento almacenado a su modelo donde pertenece.
Poner un código en Django y algún código en la base de datos es una pesadilla de mantenimiento. He pasado demasiados de mis más de 30 años en TI tratando de limpiar este tipo de desorden.
Lo que está preguntando es acerca de cómo integrar el ORM con los SP. Probablemente esto no sea posible, y el uso de procedimientos almacenados probablemente requiera que accedas a django.db.connection directamente como en las otras respuestas, pero sería interesante si pudieras mover automáticamente consultas comunes que el ORM realiza a procedimientos almacenados, para guardar en el tiempo de generación de consultas, y hacerlo de forma transparente, como una optimización. No funcionaría en todas las bases de datos, y la ganancia de rendimiento probablemente no valga la pena, pero sería divertido investigar. – Chad
@Chad: "Lo que está preguntando es sobre la integración del ORM con los SP". Entendido. De ahí mi respuesta. Los SP fragmentan la lógica de la aplicación entre el código de aplicación adecuado y la base de datos. A menudo crean más problemas de los que resuelven. Creo que los SP no son útiles bajo ninguna circunstancia y no deberían usarse. –
@ S.Lott Creo que malinterpretaste el punto que hice. Estoy hablando de un futuro/imaginario Django ORM. Los procedimientos almacenados no serán escritos por los desarrolladores. Este ORM convertirá dinámicamente/transparentemente las consultas ORM ejecutadas comúnmente en procedimientos almacenados, de modo que pueda ahorrar tiempo de generación de cadenas SQL y hacer uso de la naturaleza precompilada de SP. Una vez más, no pretendo pensar que esto sea siquiera posible, o que valdría la pena la aceleración. Solo señalé una idea interesante que su pregunta generó para mí. Este enfoque podría dejar toda la lógica en el código y tener un rendimiento de SP. – Chad
Supongo que la compatibilidad mejorada con el SQLSQL rawset en Django 1.2 puede hacer esto más fácil ya que no tendría que lanzar su propio código de tipo make_instance.
No es un buen ejemplo: https://djangosnippets.org/snippets/118/
from django.db import connection
cursor = connection.cursor()
ret = cursor.callproc("MY_UTIL.LOG_MESSAGE", (control_in, message_in))# calls PROCEDURE named LOG_MESSAGE which resides in MY_UTIL Package
cursor.close()
- 1. ¿La mejor manera de aprender los procedimientos almacenados de PostgreSQL?
- 2. ¿Cuál es la mejor manera de depurar los procedimientos almacenados (y escribir sprocs que son más fáciles de depurar)?
- 3. ¿Cuál es la mejor manera de acceder a Neo4j desde Django?
- 4. ¿Cuál es la forma más elegante de usar procedimientos almacenados?
- 5. Versiones de procedimientos almacenados
- 6. ¿Cuál es la mejor manera de migrar datos en django
- 7. Manera simple de obtener todos los procedimientos almacenados mediante programación
- 8. ¡Los procedimientos almacenados se agotan de manera intermitente!
- 9. ¿Cuál es el significado de "procedimientos almacenados precompilados"?
- 10. ¿Cuál es la mejor manera de manejar objects.get de Django?
- 11. ¿El SQL formado dinámicamente en los procedimientos almacenados niega el propósito mismo de los procedimientos almacenados?
- 12. ¿Cuál es la mejor forma de controlar la versión de los procedimientos almacenados de mi servidor SQL?
- 13. de consulta a la lista todos los procedimientos almacenados
- 14. Qué ORM es el mejor cuando se utilizan procedimientos almacenados
- 15. ¿Accediendo a procedimientos almacenados con robconery/masivo?
- 16. ¿Cuál es la mejor manera de probar un procedimiento almacenado?
- 17. ¿Cuál es la mejor manera de definir y acceder a las propiedades seleccionadas en C#?
- 18. ¿La mejor manera de acceder a píxeles en OpenGL?
- 19. Procedimientos almacenados a archivos .sql
- 20. WebMatrix y procedimientos almacenados
- 21. ¿Cuál es la mejor manera de acceder a Google Calendar desde ruby?
- 22. MySQL: ¿Cómo modificar los procedimientos almacenados atómicamente?
- 23. ¿Cómo llamo a los procedimientos almacenados de MySQL desde Perl?
- 24. Consultas de LINQ frente a Procedimientos almacenados
- 25. Procedimientos almacenados Ingeniería inversa
- 26. Depuración de procedimientos almacenados en Management studio
- 27. Procedimientos almacenados - Fin de días
- 28. Procedimientos almacenados en el sistema de control de fuente
- 29. Eliminar todos los procedimientos almacenados en MySQL o usar procedimientos almacenados temporales
- 30. ¿Cuál es la mejor manera de comunicarse entre los AppDomains?
[Django Uso de procedimientos almacenados] (http://www.djangosnippets.org/snippets/118) dará una idea. – Dhana