Модель Django на основе табличной функции SQL с использованием MyModel.objects.raw()

#sql-server #django #django-models #django-rest-framework #pyodbc

#sql-сервер #django #django-модели #django-rest-framework #pyodbc

Вопрос:

Если это уместно, я использую Django с Django Rest Framework, django-mssql-backend и pyodbc

Я создаю некоторые модели устаревшей базы данных, доступные только для чтения, используя довольно сложные запросы и функциональность Django MyModel.objects.raw(). Первоначально я выполнял запрос как запрос выбора, который работал хорошо, однако я получил запрос попытаться сделать то же самое, но с табличной функцией из базы данных.

Выполнение этого:

 MyModel.objects.raw(select * from dbo.f_mytablefunction)
  

Выдает ошибку: недопустимое имя объекта ‘myapp_mymodel’.
При более глубоком изучении локальных переменных во время ошибки создается впечатление, что этот SQL:

 'SELECT [myapp_mymodel].[Field1], '
 '[myapp_mymodel].[Field2] FROM '
 '[myapp_mymodel] WHERE '
 '[myapp_mymodel].[Field1] = %s'
  

Сама модель правильно сопоставляется с запросом при выполнении эквивалентного:

 MyModel.objects.raw(select * from dbo.mytable)
  

Возвращает данные, как и ожидалось, и dbo.f_mytablefunction определяется как:

 CREATE FUNCTION dbo.f_mytablefunction
(
     @param1 = NULL etc etc
)
RETURNS TABLE
AS
RETURN
(
    SELECT
            field1, field2 etc etc
        FROM            
            dbo.mytable
)
  

Если у кого-нибудь есть какие-либо объяснения относительно того, почему эти два режима работы обрабатываются по-разному, я был бы очень рад узнать.

Ответ №1:

Думаю, вы уже поняли это (см. Документы):

 MyModel.objects.raw('select * from dbo.f_mytablefunction(%s)', [1])
  

Если вы хотите сопоставить свою табличную функцию с моделью, в этом gist есть довольно тщательный подход, хотя лицензия не упоминается.

После того, как вы указали «объекты» своей модели в новый TableFunctionManager и добавили упорядоченный параметр «function_args» (см. Тесты в gist), вы можете запросить его следующим образом:

 MyModel.objects.all().table_function(param1=1)
  

Для тех, кто интересуется вариантами использования табличных функций, попробуйте выполнить поиск ‘your_db_vendor tvf’.