如何使用python在存储过程中将对象类型作为in-OUT参数传递

2024-09-30 06:26:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个带有三个模式的遗留数据模型。数据、视图和api。表存储在数据中,视图存储在视图中,过程存储在api中。现在我想使用django为它构建一个应用程序。在api中,我使用自定义类型作为参数的过程来存储数据、编写历史记录并关注用户权限和日志记录

我制作了一个不由Django管理的模型,并尝试覆盖save方法:

from django.db import models
from django.db import connection

class Mandator(models.Model):
    mdt_id          = models.IntegerField(primary_key=True)
    mdt_guid = models.UUIDField(default=uuid.uuid4,
                                editable=False)
    mdt_name        = models.CharField(max_length=100)
    mdt_insert_date = models.DateField()
    mdt_insert_user = models.CharField(max_length=100)
    mdt_update_date = models.DateField()
    mdt_update_user = models.CharField(max_length=100)

    class Meta:
       managed = False
       db_table = 'fdb_mandator'

    def save(self, *args, **kwargs):
        with connection.cursor() as cursor:
            cursor.callproc('prc_fdb_mandator_insert',[self])

在执行save方法时,出现以下错误:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/*****/Workspaces/FlexDB/flexdb-django/flexdb/fmgr/models/mandator.py", line 19, in save
    cursor.callproc('prc_fdb_mandator_insert',[self])
  File "/home/*****/.local/lib/python3.7/site-packages/django/db/backends/utils.py", line 65, in callproc
    return self.cursor.callproc(procname, params, kparams)
  File "/home/*****/.local/lib/python3.7/site-packages/django/db/utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/home/*****/.local/lib/python3.7/site-packages/django/db/backends/utils.py", line 62, in callproc
    return self.cursor.callproc(procname, params)
django.db.utils.ProgrammingError: can't adapt type 'Mandator'

数据库是PostResql12

类型:

create type fdb_mandator_ot as
(
    mdt_id          integer,
    mdt_guid        uuid,
    mdt_name        varchar(255),
    mdt_insert_date date,
    mdt_insert_user varchar(255),
    mdt_update_date date,
    mdt_update_user varchar(255)
);

程序框架:

create procedure prc_fdb_mandator_insert(INOUT p_mdt fdb_mandator_ot, p_username character varying DEFAULT NULL::character varying)
    language plpgsql
as
$$
DECLARE
    l_prc_name  VARCHAR := 'prc_fdb_mandator_insert';
BEGIN
    .
    .
    .
END;
$$;

使用代码:

cursor.execute('CALL prc_fdb_mandator_insert(fdb_mandator_ot(%s,%s,%s,%s,%s,%s,%s))',
                            [self.mdt_id, 
                             None, 
                             self.mdt_name, 
                             self.mdt_insert_date, 
                             self.mdt_insert_user, 
                             self.mdt_update_date, 
                             self.mdt_update_user])

没有错误,但数据库中没有新条目

与:

cursor.execute('''DO
                  $$
                  DECLARE
                      l_mdt   fdb_mandator_ot;
                  BEGIN
                      l_mdt.mdt_id := %s;
                      l_mdt.mdt_name := %s;
 
                      CALL prc_fdb_mandator_insert(l_mdt);
 
                  END;
                  $$''',[self.mdt_id, self.mdt_name])

数据在数据库中,但没有输出参数(mdt_id为null),很难写入

有人知道如何用python将对象类型传递给存储过程吗


Tags: djangonameselfiddbdatemodelsupdate
1条回答
网友
1楼 · 发布于 2024-09-30 06:26:34

我现在有了一个有效的解决方案。我编写了一个包装函数,并按照以下方式进行调用:

def save(self, *args, **kwargs):
        with connection.cursor() as cursor:
            if self.mdt_id:
                query = "SELECT * FROM fnc_fdb_mandator_update(ROW(%s,%s,%s,%s,%s,%s,%s))"
            else:
                query = "SELECT * FROM fnc_fdb_mandator_insert(ROW(%s,%s,%s,%s,%s,%s,%s))"

            cursor.execute(query,
                           [self.mdt_id,
                            self.mdt_guid,
                            self.mdt_name,
                            self.mdt_insert_date,
                            self.mdt_insert_user,
                            self.mdt_update_date,
                            self.mdt_update_user])
            row = cursor.fetchone()
            self.mdt_id = row[0]
            self.mdt_guid = row[1]
            self.mdt_name = row[2]
            self.mdt_insert_date = row[3]
            self.mdt_insert_user = row[4]
            self.mdt_update_date = row[5]

德扬戈壳牌公司的Testausgabe auf:

>>> from fmgr.models import Mandator
>>> m=Mandator()
>>> m.mdt_name="Test Mandator 1"
>>> 
>>> print(m.mdt_id)
None
>>> print(m.mdt_name)
Test Mandator 1
>>> print(m.mdt_guid)
5e8b7baa-8be9-485e-8c8f-99c18153120b
>>> print(m.mdt_insert_date)
None
>>> print(m.mdt_update_date)
None
>>> 
>>> m.save()
>>> print(m.mdt_id)
2
>>> print(m.mdt_name)
Test Mandator 1
>>> print(m.mdt_guid)
5e8b7baa-8be9-485e-8c8f-99c18153120b
>>> print(m.mdt_insert_date)
2020-07-01
>>> print(m.mdt_update_date)
None
>>> 
>>> m.mdt_name="Test Mandator 111"
>>> m.save()
>>> print(m.mdt_id)
2
>>> print(m.mdt_name)
Test Mandator 111
>>> print(m.mdt_guid)
5e8b7baa-8be9-485e-8c8f-99c18153120b
>>> print(m.mdt_insert_date)
2020-07-01
>>> print(m.mdt_update_date)
2020-07-01

相关问题 更多 >

    热门问题