Vas*_*sil 65 python postgresql orm uuid sqlalchemy
如果使用PostgreSQL(Postgres),有没有办法在SQLAlchemy中将列(主键)定义为UUID?
JDi*_*teo 80
sqlalchemy postgres方言支持UUID列.这很容易(问题特别是postgres) - 我不明白为什么其他答案都那么复杂.
这是一个例子:
from sqlalchemy.dialects.postgresql import UUID
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class Foo(db.Model):
id = db.Column(db.Integer, primary_key=True)
uuid = db.Column(UUID(as_uuid=True), unique=True, nullable=False)
Run Code Online (Sandbox Code Playgroud)
Tom*_*lis 62
我写了这个,域名已经消失,但这里是胆量....
无论我真正关心正确数据库设计的同事如何看待用于关键字段的UUID和GUID.我经常发现我需要这样做.我认为它比自动增量有一些优势使它值得.
在过去的几个月里,我一直在改进UUID列类型,我想我终于搞定了.
from sqlalchemy import types
from sqlalchemy.dialects.mysql.base import MSBinary
from sqlalchemy.schema import Column
import uuid
class UUID(types.TypeDecorator):
impl = MSBinary
def __init__(self):
self.impl.length = 16
types.TypeDecorator.__init__(self,length=self.impl.length)
def process_bind_param(self,value,dialect=None):
if value and isinstance(value,uuid.UUID):
return value.bytes
elif value and not isinstance(value,uuid.UUID):
raise ValueError,'value %s is not a valid uuid.UUID' % value
else:
return None
def process_result_value(self,value,dialect=None):
if value:
return uuid.UUID(bytes=value)
else:
return None
def is_mutable(self):
return False
id_column_name = "id"
def id_column():
import uuid
return Column(id_column_name,UUID(),primary_key=True,default=uuid.uuid4)
# Usage
my_table = Table('test',
metadata,
id_column(),
Column('parent_id',
UUID(),
ForeignKey(table_parent.c.id)))
Run Code Online (Sandbox Code Playgroud)
我认为存储为二进制(16字节)最终应该比字符串表示(36字节?)更有效,并且似乎有一些迹象表明索引16字节块在mysql中应该比字符串更有效.不管怎样,我不认为它会更糟.
我发现的一个缺点是,至少在phpymyadmin中,你无法编辑记录,因为它隐式地尝试对"select*from table where id = ..."进行某种字符转换,并且存在各种显示问题.
除此之外,一切似乎都很好,所以我把它扔出去了.如果你看到一个明显的错误,请发表评论.我欢迎任何改进它的建议.
除非我遗漏了某些内容,否则如果底层数据库具有UUID类型,则上述解决方案将起作用.如果没有,则在创建表时可能会出错.我提出的解决方案是我最初的目标是MSSqlServer,最后是MySql,所以我认为我的解决方案更灵活,因为它似乎在mysql和sqlite上工作正常.还没有打扰检查postgres.
小智 20
如果您对具有UUID值的"String"列感到满意,这里有一个简单的解决方案:
def generate_uuid():
return str(uuid.uuid4())
class MyTable(Base):
__tablename__ = 'my_table'
uuid = Column(String, name="uuid", primary_key=True, default=generate_uuid)
Run Code Online (Sandbox Code Playgroud)
con*_*gus 16
SQLAlchemy 2.0 添加了UUID 类型,这是与数据库无关的类型的 SQL 本机形式,它向后兼容以前的仅 PostgreSQL 版本的 UUID。
例子:
import sqlalchemy as sa
from sqlalchemy.orm import DeclarativeBase, Mapped
class Base(DeclarativeBase):
pass
class MyModel(Base):
my_field: Mapped[sa.UUID]
Run Code Online (Sandbox Code Playgroud)
Ber*_*pac 13
我使用UUIDType
了SQLAlchemy-Utils
包中的内容:http://sqlalchemy-utils.readthedocs.org/en/latest/data_types.html#module-sqlalchemy_utils.types.uuid
Gra*_*nat 10
由于您使用的是 Postgres,因此应该可以:
from app.main import db
from sqlalchemy.dialects.postgresql import UUID
class Foo(db.Model):
id = db.Column(UUID(as_uuid=True), primary_key=True)
name = db.Column(db.String, nullable=False)
Run Code Online (Sandbox Code Playgroud)
这是一种基于SQLAlchemy 文档中后端不可知 GUID的方法,但使用 BINARY 字段将 UUID 存储在非 postgresql 数据库中。
import uuid
from sqlalchemy.types import TypeDecorator, BINARY
from sqlalchemy.dialects.postgresql import UUID as psqlUUID
class UUID(TypeDecorator):
"""Platform-independent GUID type.
Uses Postgresql's UUID type, otherwise uses
BINARY(16), to store UUID.
"""
impl = BINARY
def load_dialect_impl(self, dialect):
if dialect.name == 'postgresql':
return dialect.type_descriptor(psqlUUID())
else:
return dialect.type_descriptor(BINARY(16))
def process_bind_param(self, value, dialect):
if value is None:
return value
else:
if not isinstance(value, uuid.UUID):
if isinstance(value, bytes):
value = uuid.UUID(bytes=value)
elif isinstance(value, int):
value = uuid.UUID(int=value)
elif isinstance(value, str):
value = uuid.UUID(value)
if dialect.name == 'postgresql':
return str(value)
else:
return value.bytes
def process_result_value(self, value, dialect):
if value is None:
return value
if dialect.name == 'postgresql':
return uuid.UUID(value)
else:
return uuid.UUID(bytes=value)
Run Code Online (Sandbox Code Playgroud)
Flo*_*sch -21
您可以尝试编写自定义类型,例如:
import sqlalchemy.types as types
class UUID(types.TypeEngine):
def get_col_spec(self):
return "uuid"
def bind_processor(self, dialect):
def process(value):
return value
return process
def result_processor(self, dialect):
def process(value):
return value
return process
table = Table('foo', meta,
Column('id', UUID(), primary_key=True),
)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
42522 次 |
最近记录: |