Получение неправильного вывода из процедуры / функции PostgreSQL в Django API

#python #django #postgresql #stored-procedures #psycopg2

#python #django #postgresql #хранимые процедуры #psycopg2

Вопрос:

У меня есть моя база данных и все ее процедуры, готовые в PostgreSQL. Ранее я использовал Laravel в качестве серверной части моего API, и все процедуры работали правильно и возвращали правильный вывод.

Моя функция контроллера Laravel для одного из вызовов API выглядит следующим образом:

 public function retrieve() {
    $data = DB::select(DB::raw("SELECT * FROM showallmenuitem()"));
    $status = count($data);

    return $status ? response(['message'=>'Menu item retrieved successfully','data' =>$data],200):response(['message'=>'Failed to retrieve menu item.']);
}
  

Этот метод вызывает showallmenuitem() процедуру, и результат, сохраненный в $data переменной, выглядит следующим образом:

 {
    "message": "Menu item retrieved successfully",
    "data": [
        {
            "meniuid": 1,
            "menuitemsname": "User"
        },
        {
            "meniuid": 2,
            "menuitemsname": "Payment"
        }
    ]
}
  

Но недавно я сменил свой серверный сервер с Laravel на Django, потому что мне нужна некоторая функциональность AI в моем приложении, а модели AI, которые мне нужны, написаны на python. Итак, я создал простое представление для вызова той же процедуры из Django. Я ожидал того же результата, что и Laravel, но Django выдает мне вывод в неправильном формате. Я использую psycopg2 в качестве драйверов базы данных.
Вот мой код представления Django:

 @csrf_exempt
def retrieve(request):
    if request.method == 'GET':
        with connection.cursor() as cursor:
            cursor.callproc("showallmenuitem")
            results = cursor.fetchall()

        response = {
            'message'       :   'Menu items retrieved successfully',
            'data'          :   results
            }

        return JsonResponse(response, safe=False, status= 200)
  

И я получил вывод в следующем формате:

 {
    "message": "Menu items retrieved successfully",
    "data": [
        [
            1,
            "User"
        ],
        [
            2,
            "Payment"
        ],
    ]
}
  

Note: Я также попытался запустить execute функцию вместо callproc того, как написано ниже, и все равно получаю тот же результат.

         with connection.cursor() as cursor:
            cursor.execute("SELECT * FROM showallmenuitem()")
            results = cursor.fetchall()
  

Итак, мой вопрос в том, как получить вывод в правильном формате json в Django, как я получаю из Laravel?

Ответ №1:

По умолчанию psycopg2 возвращает список кортежей, который вы видите преобразованным в JSON массив массивов. Чтобы изменить это, смотрите Здесь:

https://docs.djangoproject.com/en/3.0/topics/db/sql/

Прямое выполнение пользовательского SQL

По умолчанию Python DB API возвращает результаты без их имен полей, что означает, что в итоге вы получаете список значений, а не dict . При небольшой производительности и затратах памяти вы можете возвращать результаты в виде dict, используя что-то вроде этого:

 def dictfetchall(cursor):
    "Return all rows from a cursor as a dict"
    columns = [col[0] for col in cursor.description]
    return [
        dict(zip(columns, row))
        for row in cursor.fetchall()
    ]