문제

나는 상당히 복잡한 데이터베이스를 설계하고 있으며, 일부 쿼리는 Django의 ORM의 범위를 훨씬 벗어날 것임을 알고 있습니다. Django의 ORM과 SP를 통합 한 사람이 있습니까? 그렇다면 어떤 RDBMS와 어떻게 했습니까?

도움이 되었습니까?

해결책

우리 (Musicpictures.com / eviscape.com)는 Django 스 니펫을 썼지 만 전체 스토리는 아니라고 썼습니다 (실제로 그 코드는 그 당시 Oracle에서만 테스트되었습니다).

저장된 절차는 시도 및 테스트 된 SP 코드를 재사용하려고하거나 하나의 SP 호출이 데이터베이스에 대한 여러 통화보다 빠르거나 보안이 데이터베이스에 대한 조정 된 액세스가 필요한 경우 또는 쿼리가 매우 복잡한 / 멀티 스펙트 인 경우에 적합합니다. 우리는 Oracle 및 Postgres 데이터베이스에 대한 하이브리드 모델/SP 접근법을 사용하고 있습니다.

요령은 사용하기 쉽고 "Django"처럼 유지하는 것입니다. 우리는 커서의 결과를 취하고 커서에서 채워진 모델의 인스턴스를 생성하는 make_instance 함수를 사용합니다. 커서가 추가 필드를 반환 할 수 있기 때문에 좋습니다. 그런 다음 일반적인 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

# 다음과 같이 사용하십시오.

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

# 그리고 다음은 몇 가지 헬퍼 기능입니다.

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]    

건배, 사이먼.

다른 팁

Django에서 연결 유틸리티를 사용해야합니다.

from django.db import connection

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

그런 다음 데이터를 가져올 수 있습니다.

cursor.fetchone()

또는:

cursor.fetchall()

추가 정보는 여기에 있습니다 : http://docs.djangoproject.com/en/dev/topics/db/sql/

좋은 예가 있습니다. 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()

SP를 사용하는 실제 실행 프로젝트를보고 싶다면 확인하십시오. 미니 북. 많은 맞춤형 SQL과 sp에 postgres pl/pgsql을 사용합니다. 나는 그들이 결국 SP를 제거 할 것이라고 생각합니다 (정당화 트랙 티켓 92).

하지 않다.

진지하게.

저장된 프로 시저 로직을 모델로 이동하십시오.

Django에 일부 코드를 넣고 데이터베이스에 일부 코드를 넣는 것은 유지 보수 악몽입니다. 나는 이런 종류의 혼란을 정리하려고 30 년 이상을 너무 많이 보냈다.

Django 1.2의 개선 된 원시 SQL 쿼리 세트 지원이 자신의 make_instance 유형 코드를 롤링 할 필요가 없으므로 더 쉽게 만들 수 있다고 생각합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top