SQLAlchemy에서 UUID를 사용하려면 어떻게 해야 합니까?
PostgreSQL(Postgres)을 사용하는 경우 SQLAlchemy에서 열(기본 키)을 UUID로 정의하는 방법이 있습니까?
sqlalchemy postgres 방언은 UUID 열을 지원합니다.이것은 쉽다 (그리고 질문은 구체적으로 사후적이다) -- 저는 왜 다른 답들이 모두 그렇게 복잡한지 이해할 수 없습니다.
다음은 예입니다.
from sqlalchemy.dialects.postgresql import UUID
from flask_sqlalchemy import SQLAlchemy
import uuid
db = SQLAlchemy()
class Foo(db.Model):
id = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
패스하는 것을 놓치지 않도록 주의하세요.callable
uuid.uuid4
로, 함수 자체를 호출대자정의로신으로 보다.uuid.uuid4()
그렇지 않으면 이 클래스의 모든 인스턴스에 대해 동일한 스칼라 값을 갖게 됩니다.자세한 내용은 여기:
이 열의 기본값을 나타내는 스칼라, Python 호출 가능 또는 ColumnElement 식으로, 삽입 시 이 열이 삽입의 VALUE 절에 지정되지 않은 경우 호출됩니다.
내가 이것을 썼고 도메인은 사라졌지만 여기 배짱이 있습니다.
적절한 데이터베이스 설계에 관심이 많은 동료들이 키 필드에 사용되는 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)))
저는 바이너리(16바이트)로 저장하는 것이 문자열 표현(36바이트?)보다 더 효율적일 것이라고 생각합니다. 그리고 mysql에서 16바이트 블록을 인덱싱하는 것이 문자열보다 더 효율적이라는 지적도 있는 것 같습니다.저는 어쨌든 그것이 더 나빠질 것이라고 기대하지 않을 것입니다.
제가 발견한 한 가지 단점은 적어도 phpymyadmin에서 레코드를 편집할 수 없다는 것입니다. 왜냐하면 id가 =인 테이블에서 선택 *에 대해 암묵적으로 일종의 문자 변환을 시도하고 기타 표시 문제가 있기 때문입니다.
그 외에는 모든 것이 잘 작동하는 것 같아서, 저는 그것을 밖에 버리고 있습니다.명백한 오류가 발견되면 댓글을 남겨주세요.저는 그것을 개선하기 위한 어떠한 제안도 환영합니다.
기본 데이터베이스에 UUID 유형이 있으면 위의 솔루션이 작동합니다.그렇지 않으면 테이블을 만들 때 오류가 발생할 수 있습니다.제가 생각해낸 솔루션은 원래 MSSqlServer를 목표로 하다가 결국 MySql로 갔기 때문에 mysql과 sqlite에서 잘 작동하는 것 같아 제 솔루션이 조금 더 유연하다고 생각합니다.아직 우편물 확인하는 것을 귀찮아하지 않았습니다.
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)
나는 그것을 사용했습니다.UUIDType
포장에서.
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)
다음은 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)
관심 있는 사람이 있으면 Tom Willis answer를 사용했지만 uuid에 문자열을 추가하는 데 유용했습니다.process_bind_param 메서드의 UUID 변환
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
동일한 문제가 발생했습니다. 이 문제가 해결될 것입니다. 저에게 적합합니다.
from sqlalchemy import Column, text
from sqlalchemy.dialects.postgresql import UUID
Column(
"id", UUID(as_uuid=True),
primary_key=True,
server_default=text("gen_random_uuid()"),
)
Postgre를 사용하는 경우SQL < 14, 이 확장 팩을 추가해야 할 것 같습니다.
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
사용할 수 있습니다.uuid_generate_v4()
또한 다음과 같이 확장 팩을 추가해야 합니다.
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
우리는 사용할 수 있습니다.UUIDType
,
from sqlalchemy_utils import UUIDType
from sqlalchemy import String
class User(Base):
id = Column(UUIDType(binary=False), primary_key=True, default=uuid.uuid4)
name = Column(String)
자세한 내용은 공식 문서를 참조하십시오.
SQLLchemy 2.0은 이전 Postgre와 역호환되는 데이터베이스 독립형의 SQL-네이티브 형식인 UUID 유형을 추가합니다.SQL 전용 버전의 UUID입니다.
예:
import sqlalchemy as sa
from sqlalchemy.orm import DeclarativeBase, Mapped
class Base(DeclarativeBase):
pass
class MyModel(Base):
my_field: Mapped[sa.UUID]
다음과 같은 사용자 지정 유형을 작성해 볼 수 있습니다.
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),
)
언급URL : https://stackoverflow.com/questions/183042/how-can-i-use-uuids-in-sqlalchemy
'programing' 카테고리의 다른 글
노드를 제거합니다.Linux 명령줄을 사용하는 JS? (0) | 2023.05.31 |
---|---|
탐색 스택에서 뷰 컨트롤러 제거 (0) | 2023.05.31 |
Flow Layout Panel - 컨트롤의 자동 너비? (0) | 2023.05.31 |
NSMutableArray를 NSAray로 변환하려면 어떻게 해야 합니까? (0) | 2023.05.31 |
:active pseudo-class는 모바일 사파리에서 작동하지 않습니다. (0) | 2023.05.31 |