Có cách nào để xác định cột (khóa chính) dưới dạng UUID trong SQLAlchemy nếu sử dụng PostgreSQL (Postgres) không?Làm cách nào để sử dụng UUID trong SQLAlchemy?
Trả lời
Bạn có thể thử viết một custom type, ví dụ:
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),
)
Điều này thậm chí không hoạt động, nó chỉ là một công việc cắt và dán từ ví dụ kiểu giả từ các tài liệu. Câu trả lời của Tom Willis dưới đây là tốt hơn nhiều. –
Ngoài [câu trả lời của Florian] (http://stackoverflow.com/questions/183042/how-can-i-use-uuids-in-sqlalchemy/188427#188427), cũng có [mục blog này] (http: //blog.sadphaeton.com/2009/01/19/sqlalchemy-recipeuuid-column.html). Nó trông tương tự ngoại trừ nó phân lớp 'types.TypeDecorator' thay vì' types.TypeEngine'. Liệu một trong hai cách tiếp cận có một lợi thế hay bất lợi so với một trong những khác? –
Không cần một 'default =? '? ví dụ. 'Cột ('id', UUID(), primary_key = Đúng, mặc định =
I wrote this và tên miền được đi nhưng đây là ruột ....
Bất kể thế nào đồng nghiệp của tôi, người thực sự quan tâm về cơ sở dữ liệu thích hợp cảm giác thiết kế về UUID và GUID được sử dụng cho các trường khóa. Tôi thường thấy tôi cần phải làm điều đó. Tôi nghĩ rằng nó có một số lợi thế hơn autoincrement mà làm cho nó có giá trị nó.
Tôi đã tinh chỉnh một loại cột UUID trong vài tháng qua và tôi nghĩ rằng cuối cùng tôi đã nhận được nó vững chắc.
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)))
Tôi tin lưu trữ như nhị phân (16 byte) nên kết thúc được hiệu quả hơn so với các đại diện chuỗi (36 byte?), Và có vẻ là một số dấu hiệu cho thấy lập chỉ mục 16 byte khối nên hiệu quả hơn trong mysql so với chuỗi. Tôi sẽ không mong đợi nó sẽ tồi tệ hơn anyway.
Một bất lợi mà tôi thấy là ít nhất trong phpymyadmin, bạn không thể chỉnh sửa hồ sơ vì nó ngầm cố gắng thực hiện một số loại chuyển đổi ký tự cho "select * from table id = ..." và ở đó các vấn đề hiển thị khác.
Khác với tất cả mọi thứ dường như hoạt động tốt, và vì vậy tôi đang ném nó ra khỏi đó. Để lại một bình luận nếu bạn thấy một lỗi rõ ràng với nó. Tôi hoan nghênh mọi đề xuất để cải thiện nó.
Trừ khi tôi thiếu điều gì đó, giải pháp trên sẽ hoạt động nếu cơ sở dữ liệu bên dưới có loại UUID. Nếu không, bạn có thể sẽ gặp lỗi khi tạo bảng. Các giải pháp tôi đã đưa ra với tôi đã được nhắm mục tiêu MSSqlServer ban đầu và sau đó đã đi MySql cuối cùng, vì vậy tôi nghĩ rằng giải pháp của tôi là một chút linh hoạt hơn vì nó có vẻ làm việc tốt trên mysql và sqlite. Đã không làm phiền kiểm tra postgres được nêu ra.
Điều này lẽ ra phải được chọn làm câu trả lời, tôi đoán bạn đã đăng nó sau này. –
vâng tôi đã đăng nó sau khi tôi thấy giới thiệu từ câu trả lời của Jacob. –
Lưu ý rằng nếu bạn đang sử dụng phiên bản 0.6 hoặc cao hơn, câu lệnh nhập MSBinary trong giải pháp của Tom nên được thay đổi thành "từ sqlalchemy.dialects.mysql.base nhập MSBinary". Nguồn: http://www.mail-archive.com/[email protected]/msg18397.html –
Xem thêm công thức cho Backend-agnostic GUID Type trong tài liệu SQLAlchemy cho các loại cột.
Trong trường hợp có ai quan tâm, tôi đã sử dụng Tom Willis câu trả lời, nhưng không tìm thấy hữu ích để thêm một chuỗi để chuyển đổi uuid.UUID trong phương pháp process_bind_param
class UUID(types.TypeDecorator):
impl = types.LargeBinary
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 isinstance(value, basestring):
return uuid.UUID(value).bytes
elif value:
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
Dưới đây là một cách tiếp cận dựa trên Backend agnostic GUID từ tài liệu SQLAlchemy, nhưng sử dụng một trường BINARY để lưu trữ UUID trong cơ sở dữ liệu không phải 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)
Cách sử dụng này sẽ là gì? – codeninja
Tôi đã sử dụng UUIDType
từ SQLAlchemy-Utils
gói: http://sqlalchemy-utils.readthedocs.org/en/latest/data_types.html#module-sqlalchemy_utils.types.uuid
Tôi hiện đang cố gắng sử dụng vấn đề này, tôi gặp phải lỗi: 'nâng InvalidStatus (" notfound: {k}. (Cls = {cls}) ". Định dạng (k = k, cls = cls))' 'alchemyjsonschema.InvalidStatus: notfound: BINARY (16). (cls =
Nếu bạn hài lòng với một 'String' cột có giá trị UUID, ở đây đi một giải pháp đơn giản:
def generate_uuid():
return str(uuid.uuid4())
class MyTable(Base):
__tablename__ = 'my_table'
uuid = Column(String, name="uuid", primary_key=True, default=generate_uuid)
Thật không may [Loại GUID độc lập phụ trợ] (http://docs.sqlalchemy.org/en/rel_0_9/core/custom_types.html?highlight=guid#backend-agnostic-guid-type) từ tài liệu SQLAlchemy cho các loại cột dường như không để làm việc cho các khóa chính trong các cơ sở dữ liệu SQLite. Không hẳn là đại kết như tôi mong đợi. – adamek