AttributeError:“UUID”对象在使用后端不可知GUID类型时没有属性“replace”

2024-04-25 20:19:35 发布

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

我想在使用SQLAlchemy 1.1.5的Postgresql数据库中有一个uuid类型的主键id,它使用pg8000适配器连接到数据库。我使用了SQLAlchemy文档中的Backend-agnostic GUID Type recipe

当我想插入数据库时,我得到以下错误

  File ".../guid.py", line ???, in process_result_value
    return uuid.UUID(value)
  File "/usr/lib/python2.7/uuid.py", line 131, in __init__
    hex = hex.replace('urn:', '').replace('uuid:', '')
AttributeError: 'UUID' object has no attribute 'replace'

我的模特像这样

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
from guid import GUID
import uuid

base = declarative_base()

class Item(base):
    __tablename__ = 'item'

    id = Column(GUID(), default=uuid.uuid4, nullable=False, unique=True, primary_key=True)
    name = Column(String)
    description = Column(String)

    def __repr__(self):
        return "<Item(name='%s', description='%s')>" % (self.name, self.description)

我的资源或控制器如下所示

data = req.params
item = Item(name=data['name'], description=data['description'])

self.session.add(item)
self.session.commit()

Tags: namefromimportself数据库basestringuuid
3条回答

这应该可以解决它:

id = Column(GUID(as_uuid=True), ...)

来自https://bitbucket.org/zzzeek/sqlalchemy/issues/3323/in-099-uuid-columns-are-broken-with

"If you want to pass a UUID() object, the as_uuid flag must be set to True."

当跨系统使用uuid时,这会相当令人沮丧。在某些情况下,很难控制UUID是作为字符串还是作为原始UUID传入。为了解决这个问题,像这样的解决方案可能会奏效。我附上了医生的例子,以确保其他一切都是正确的。

# TODO: Set this up such that the normal uuid interface is available as a pass through
import uuid

class UUID(uuid.UUID):

    def __init__(self, hex=None, bytes=None, bytes_le=None, fields=None,
                       int=None, version=None):

        if hex and (issubclass(type(hex), uuid.UUID) or isinstance(hex, uuid.UUID)):
            hex = str(hex)

        super(UUID, self).__init__(hex=hex, bytes=bytes, bytes_le=bytes_le, fields=fields, int=int, version=version)

print(UUID(uuid4())) # Now this works!

print(UUID('{12345678-1234-5678-1234-567812345678}'))
print(UUID('12345678123456781234567812345678'))
print(UUID('urn:uuid:12345678-1234-5678-1234-567812345678'))
print(UUID(bytes=b'\x12\x34\x56\x78' * 4)) # Python 3 requires this to be prefixed with b''. Docs appear to be mainly for Python 2
print(UUID(bytes_le=b'\x78\x56\x34\x12\x34\x12\x78\x56' +
              b'\x12\x34\x56\x78\x12\x34\x56\x78'))
print(UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678)))
print(UUID(int=0x12345678123456781234567812345678))

请自行决定,这只是一个例子。

PostgreSQL数据库适配器正在返回一个uuid.UUID()对象(请参阅它们的type mapping documentation,SQLAlchemy已将其传递给^{} method

然而,文档中给出的实现需要一个字符串,因此失败:

>>> import uuid
>>> value = uuid.uuid4()
>>> uuid.UUID(value)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python2.7/uuid.py", line 133, in __init__
    hex = hex.replace('urn:', '').replace('uuid:', '')
AttributeError: 'UUID' object has no attribute 'replace'

快速解决方法是强制该值为字符串:

def process_result_value(self, value, dialect):
    if value is None:
        return value
    else:
        return uuid.UUID(str(value))

或者可以先测试类型:

def process_result_value(self, value, dialect):
    if value is None:
        return value
    else:
        if not isinstance(value, uuid.UUID):
            value = uuid.UUID(value)
        return value

我提交了pull request #403以在文档中修复此问题(自合并后)。

相关问题 更多 >