Random ids in sqlalchemy (pylons)

匿名 (未验证) 提交于 2019-12-03 02:58:02

问题:

I'm using pylons and sqlalchemy and I was wondering how I could have some randoms ids as primary_key.

回答1:

the best way is to use randomly generated UUIDs:

import uuid  id = uuid.uuid4() 

uuid datatypes are available natively in some databases such as Postgresql (SQLAlchemy has a native PG uuid datatype for this purpose - in 0.5 its called sqlalchemy.databases.postgres.PGUuid). You should also be able to store a uuid in any 16 byte CHAR field (though I haven't tried this specifically on MySQL or others).



回答2:

i use this pattern and it works pretty good. source

from sqlalchemy import types from sqlalchemy.databases.mysql 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))) 

Though zzzeek I believe is the author of sqlalchemy, so if this is wrong he would know, and I would listen to him.



回答3:

Or with ORM mapping:

import uuid from sqlalchemy import Column, Integer, String, Boolean  def uuid_gen():     return str(uuid.uuid4())  Base = declarative_base() class Device(Base):     id = Column(String, primary_key=True, default=uuid_gen) 

This stores it as a string providing better database compatibility. However, you lose the database's ability to more optimally store and use the uuid.



回答4:

Years later with this problem again so I'll share my current answer. I ended up basing myself on Backend-agnostic GUID Type but I wanted to use binary instead of CHAR(32). I also wanted to deal with hex strings directly instead of UUID objects for easy printing to the user/url.

import binascii import uuid from sqlalchemy.types import TypeDecorator, BINARY   class GUID(TypeDecorator):     impl = BINARY      def load_dialect_impl(self, dialect):         return dialect.type_descriptor(BINARY(16))      def process_bind_param(self, value, dialect):         if value is None:             return value          if not isinstance(value, bytes):             if isinstance(value, uuid.UUID):                 value = value.bytes             elif isinstance(value, str):                 value = binascii.unhexlify(value)             else:                 raise TypeError('Invalid GUID value.')          return value      def process_result_value(self, value, dialect):         if value is None:             return value         return binascii.hexlify(value).decode('ascii') 

I also made a helper function to 'order' the UUID to improve indexing efficiency based on this blog post. If you're using MySQL 8 check out UUID_TO_BIN() with the swap flag and BIN_TO_UUID() instead.

def order_uuid(uuid):     uuid_str = str(uuid).replace('-', '')     ordered_uuid = ''.join([uuid_str[12:16], uuid_str[8:12], uuid_str[0:8], uuid_str[16:]])     return ordered_uuid   def revert_order_uuid(o_uuid_str):     original_uuid_str = ''.join([o_uuid_str[8:16], o_uuid_str[4:8], o_uuid_str[0:4], o_uuid_str[16:]])     return uuid.UUID(original_uuid_str) 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!