क्या एक रास्ता (प्राथमिक कुंजी) को SQLAlchemy में UUID के रूप में परिभाषित करने का एक तरीका है यदि PostgreSQL (Postgres) का उपयोग कर रहे हैं ?
क्या एक रास्ता (प्राथमिक कुंजी) को SQLAlchemy में UUID के रूप में परिभाषित करने का एक तरीका है यदि PostgreSQL (Postgres) का उपयोग कर रहे हैं ?
जवाबों:
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, unique=True)
callable
uuid.uuid4
फ़ंक्शन को कॉल करने के बजाय कॉलम परिभाषा में पास होने से बचने के लिए सावधान रहें uuid.uuid4()
। अन्यथा, आपके पास इस वर्ग के सभी उदाहरणों के लिए समान स्केलर मान होगा। अधिक जानकारी यहाँ :
इस स्तंभ के लिए डिफ़ॉल्ट मान का प्रतिनिधित्व करने वाला एक स्केलर, पाइथन कॉल करने योग्य या स्तंभकार्य अभिव्यक्ति, जिसे सम्मिलित करने पर आमंत्रित किया जाएगा यदि यह स्तंभ सम्मिलित नहीं है, तो सम्मिलित करें के मान खंड में निर्दिष्ट नहीं है।
uuid.uuid4
)।
Column(UUID(as_uuid=True) ...)
Column
और Integer
कोड स्निपेट के शीर्ष पर आयात किए गए थे, या पढ़ने के लिए बदल दिए गए थे db.Column
औरdb.Integer
मैंने यह लिखा था और डोमेन चला गया है लेकिन यहाँ हिम्मत है ...।
इसके बावजूद कि मेरे सहकर्मी जो वास्तव में उचित डेटाबेस डिज़ाइन के बारे में परवाह करते हैं, वे 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 बाइट्स?) की तुलना में अधिक कुशल होना चाहिए, और कुछ संकेत प्रतीत होते हैं कि 16 बाइट ब्लॉकों को अनुक्रमित करना स्ट्रिंग्स की तुलना में mysql में अधिक कुशल होना चाहिए। मैं यह वैसे भी बदतर होने की उम्मीद नहीं होगी।
एक नुकसान मैंने पाया है कि कम से कम phpymyadmin में, आप रिकॉर्ड्स को संपादित नहीं कर सकते क्योंकि यह स्पष्ट रूप से "तालिका से आईडी" = "और" विविध प्रदर्शन समस्याओं के लिए कुछ प्रकार के वर्ण रूपांतरण करने की कोशिश करता है।
इसके अलावा सब कुछ ठीक काम करने लगता है, और इसलिए मैं इसे वहां फेंक रहा हूं। एक टिप्पणी छोड़ें यदि आप इसके साथ एक गड़बड़ त्रुटि देखते हैं। मैं इसमें सुधार के लिए किसी भी सुझाव का स्वागत करता हूं।
जब तक मैं कुछ याद नहीं कर रहा हूँ उपरोक्त समाधान काम करेगा अगर अंतर्निहित डेटाबेस में UUID प्रकार है। यदि ऐसा नहीं होता है, तो तालिका बनाए जाने पर आपको संभवतः त्रुटियाँ मिलेंगी। मैं जिस समाधान के साथ आया था, मैं मूल रूप से MSSqlServer को लक्षित कर रहा था और फिर अंत में MySql चला गया, इसलिए मुझे लगता है कि मेरा समाधान थोड़ा अधिक लचीला है क्योंकि यह mysql और sqlite पर ठीक काम करता है। चेकिंग परेशान नहीं है अभी तक पोस्टग्रेट्स।
sqlalchemy.dialects.postgresql.UUID
सीधे उपयोग करें। देख बैकएंड-अज्ञेयवाद GUID प्रकार
यदि आप UUID मान वाले 'स्ट्रिंग' कॉलम से खुश हैं, तो यहां एक सरल उपाय दिया गया है:
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
से उपयोग किया है SQLAlchemy-Utils
: http://sqlalchemy-utils.readthedocs.org/en/latest/data_types.html#module-sqlalchemy_utils.types.uuid
raise InvalidStatus("notfound: {k}. (cls={cls})".format(k=k, cls=cls))
alchemyjsonschema.InvalidStatus: notfound: BINARY(16). (cls=<class 'sqlalchemy_utils.types.uuid.UUIDType'>)
NameError: name 'sqlalchemy_utils' is not defined
:?
SQLAlchemy-Utils
एक तृतीय-पक्ष पैकेज है, आपको इसे पहले स्थापित करने की आवश्यकता है:pip install sqlalchemy-utils
जब से आप 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 पर आधारित एक दृष्टिकोण है , लेकिन गैर-पोस्टग्रेजल डेटाबेस में यूयूआईडी को स्टोर करने के लिए एक बायनेरी फ़ील्ड का उपयोग करना है।
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)
अगर किसी को दिलचस्पी है, तो मैं टॉम विलिस जवाब का उपयोग कर रहा हूं, लेकिन 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
आप उदाहरण के लिए, एक कस्टम प्रकार लिखने का प्रयास कर सकते हैं :
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),
)
types.TypeDecorator
इसके बजाय उपवर्ग करता है types.TypeEngine
। या तो दृष्टिकोण एक दूसरे पर एक फायदा या नुकसान है?
default=?
? जैसेColumn('id', UUID(), primary_key=True, default=<someautouuidgeneratingthing>)