Frage

ich eine ziemlich komplexe Datenbank bin der Gestaltung, und wissen, dass einige meiner Anfragen außerhalb des Bereichs von Django ORM weit sein wird. Hat jemand integrierten SPs mit Django ORM erfolgreich? Wenn ja, welche RDBMS und wie hast du es getan?

War es hilfreich?

Lösung

Wir (musicpictures.com / eviscape.com) schrieb, dass django Schnipsel aber es ist nicht die ganze Geschichte (tatsächlich wurde dieser Code nur auf Oracle zu diesem Zeitpunkt getestet).

Stored Procedures Sinn, wenn Sie versucht haben, wiederzuverwenden und SP-Code getestet oder wo ein SP Anruf wird als mehrere Anrufe auf die Datenbank schneller sein - oder wo Sicherheit moderierten Zugriff auf die Datenbank erfordert - oder wo die Abfragen sind sehr kompliziert / vielstufige. Wir verwenden einen Hybrid-Modell / SP Ansatz gegen beiden Oracle und Postgres-Datenbanken.

Der Trick ist, um es einfach, es zu benutzen und zu halten „django“ wie. Wir verwenden eine make_instance Funktion, die das Ergebnis der Cursor nimmt und erzeugt Instanzen eines Modells aus dem Cursor bevölkert. Das ist schön, da der Cursor zusätzliche Felder zurückkehren könnte. Dann können Sie diese Instanzen in Ihrem Code verwenden / templates viel wie normale django Modellobjekte.

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

# Verwenden Sie es wie folgt aus:

pictures = [make_instance(Pictures(), item) for item in picture_dict]

# Und hier sind einige Hilfsfunktionen:

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]    

prost, Simon.

Andere Tipps

Sie haben das Verbindungsdienstprogramm in Django verwenden:

from django.db import connection

cursor = connection.cursor()
cursor.execute("SQL STATEMENT CAN BE ANYTHING")

dann können Sie die Daten holen:

cursor.fetchone()

oder:

cursor.fetchall()

Weitere Informationen hier: http://docs.djangoproject.com/en / dev / Themen / db / sql /

Es ist ein gutes Beispiel:   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()

Wenn Sie bei einem tatsächlichen laufenden Projekt aussehen soll, die SP verwendet Besuche Minibücher . Ein großer Teil der benutzerdefinierten SQL und verwendet Postgres pl / pgsql für SP. Ich denke, sie werden die SP schließlich aber (Rechtfertigung in trac Ticket 92 ).

Sie nicht.

Im Ernst.

Bewegen Sie die gespeicherte Prozedur Logik in Ihr Modell, wo es hingehört.

Putting einige Code in Django und einige Code in der Datenbank ist ein Wartungs-Alptraum. Ich habe zu viele meiner mehr als 30 Jahre lang in der IT diese Art von aufzuräumen versuchen.

Ich denke, die verbesserte rohe SQL queryset Unterstützung in Django 1.2 kann dies einfacher machen, wie Sie nicht Ihren eigenen make_instance Typ-Code rollen würden.

scroll top