it-swarm.com.de

AttributeError: Objekt 'UUID' hat kein Attribut 'replace'

Ich möchte eine Primärschlüssel-ID mit dem Typ uuid in einer postgresql-Datenbank mit SQLAlchemy haben. Ich habe das GUID Skript hier verwendet.

Wenn ich in die Datenbank einfügen möchte, erhalte ich die folgende Fehlermeldung

  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'

mein modell sieht so aus

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):
    __table= '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)

Meine Ressource oder mein Controller sieht so aus

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

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

Ich verwende sqlalchemy 1.1.5 unter Debian 8 mit postgresql zusammen mit dem pg8000-Adapter. Wie kann ich dieses Problem beheben?

4
The Oracle

Der PostgreSQL-Datenbankadapter pg8000 gibt ein uuid.UUID() -Objekt zurück (siehe deren Dokumentation zur Typenzuordnung , und SQLAlchemy hat dies an die Methode TypeDecorator.process_result_value() übergeben.

Die in der Dokumentation angegebene Implementierung erwartete jedoch ein string , sodass dies fehlschlägt:

>>> 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'

Das schnelle Umgehen besteht darin, den Wert sowieso als Zeichenfolge zu erzwingen:

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

oder Sie können zuerst nach dem Typ suchen:

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

Ich habe Pull Request # 403 eingereicht, um dies in der Dokumentation zu beheben (seit dem Zusammenführen).

7
Martijn Pieters

Dies sollte das Problem beheben:

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

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

"Wenn Sie ein UUID()-Objekt übergeben möchten, muss das as_uuid-Flag auf True gesetzt sein."

2
jrc

Dies kann ziemlich frustrierend sein, wenn UUIDs in einem System verwendet werden. Unter bestimmten Umständen ist es möglicherweise schwierig zu steuern, ob eine UUID als Zeichenfolge oder als unformatierte UUID eingeht. Um dies zu umgehen, könnte eine Lösung wie diese funktionieren. Ich habe die Beispiele des Dokuments angehängt, um sicherzustellen, dass alles andere noch zutrifft.

# 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))

Bitte verwenden Sie dies nach eigenem Ermessen, dies ist nur ein Beispiel.

0
Serguei Fedorov