আমি কীভাবে ইউএসইউএলএইচডিএসএইচএলএলচেমিতে ব্যবহার করতে পারি?


94

কোনও কলামটি (প্রাথমিক কী) কোনও ইউইউডি হিসাবে হিসাবে সংজ্ঞায়িত করার কোনও উপায় আছে? SQLAlchemy যদি ব্যবহার পোস্টগ্রি (Postgres)?


4
দুর্ভাগ্যক্রমে SQLlalchemy ডকুমেন্টেশন থেকে কলাম প্রকারের জন্য ব্যাকএন্ড- অজোনস্টিক জিইউইড প্রকারটি এসকিউএল ডাটাবেস ইঞ্জিনগুলিতে প্রাথমিক কীগুলির জন্য কাজ করছে বলে মনে হয় না। আমি যেমন আশা করছিলাম তেমন একিউমেনিকাল নয়।
অ্যাডামেক

এসকিউএলএলচেমি ইউজগুলি ইউআইডিটাইপ ডেকোরেটর সরবরাহ করে , চাকাটি পুনর্বিবেচনার দরকার নেই
ফিলিপ বেজারেরা দে

উত্তর:


152

স্ক্লাচেমি ডায়ালগটি ইউআইডি কলামগুলিকে সমর্থন করে। এটি সহজ (এবং প্রশ্নটি বিশেষত পোস্টগ্রিজ) - অন্য উত্তরগুলি এত জটিল কেন তা আমি বুঝতে পারি না।

এখানে একটি উদাহরণ:

from sqlalchemy.dialects.postgresql import UUID
from flask_sqlalchemy import SQLAlchemy
import uuid

db = SQLAlchemy()

class Foo(db.Model):
    # id = db.Column(db.Integer, primary_key=True)
    id = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, unique=True, nullable=False)

callable uuid.uuid4ফাংশনটি নিজেই কল করার পরিবর্তে কলাম সংজ্ঞায় উত্তীর্ণ না হওয়ার বিষয়ে সতর্ক হন uuid.uuid4()। অন্যথায়, এই শ্রেণীর সমস্ত দৃষ্টান্তগুলির জন্য আপনার কাছে একই স্কেলারের মান থাকবে। আরও বিশদ এখানে :

এই কলামটির জন্য ডিফল্ট মানকে উপস্থাপনকারী একটি স্কেলার, পাইথন কলযোগ্য বা কলামিলেমেন্ট এক্সপ্রেশন যা এই কলামটি অন্যথায় সন্নিবেশের VALUES ধারাটিতে নির্দিষ্ট না করা থাকলে সন্নিবেষ্টিত হবে।


6
আমি আপনার সাথে সম্পূর্ণ একমত। অন্য কয়েকটি উত্তর অন্যান্য ডাটাবেসের জন্য দুর্দান্ত, তবে পোস্টগ্রাগের জন্য এটি সবচেয়ে পরিষ্কার সমাধান। (আপনি ডিফল্ট হিসাবেও সেট করতে পারেন uuid.uuid4)।
পাচা

4
আপনি একটি মেগাওয়াট সরবরাহ করতে পারেন? অথবা হয়ত ফ্লাস্ক_স্ক্ল্যাচেমির সিরিয়ালাইজারটি ইউইউডি টাইপ বোঝে? পেস্টবিনের নীচে ত্রুটিগুলির কোড, পেস্টবিন.এইচডব্লিউ 8 কেপিউইউ
ব্র্যান্ডন ডুব

4
কিছু নয়, আপনি যদি স্টুডলিব থেকে ইউইউডি অবজেক্টগুলি ব্যবহার করতে চান তবে করুনColumn(UUID(as_uuid=True) ...)
ব্র্যান্ডন ডুব

4
ধন্যবাদ! এটা চমৎকার হতে পারে যদি Columnএবং Integerকোড স্নিপেট উপরের আমদানি করা হয়, অথবা পড়তে পরিবর্তন করা হয়েছে db.Columnএবংdb.Integer
গ্রেগ Sadetsky

4
নেইফ্যান্থের দরকার নেই
ফিলিপ বেজারেরা দে সুসা

64

আমি এটি লিখেছিলাম এবং ডোমেন চলে গেছে তবে এখানে সাহস আছে ...

আমার সহকর্মীরা যারা যথাযথ ডাটাবেস ডিজাইনের বিষয়ে সত্যই যত্নশীল তা কী ক্ষেত্রগুলির জন্য ব্যবহৃত ইউআইডি এবং জিইউডি সম্পর্কে কীভাবে অনুভব করে। আমি প্রায়শই এটি করার দরকার মনে করি। আমি মনে করি এটির স্বায়ত্তশাসনের চেয়ে কিছু সুবিধা রয়েছে যা এটি এটিকে সার্থক করে তোলে।

আমি গত কয়েক মাস ধরে একটি ইউআইডি কলামের ধরণটি সংশোধন করছি এবং আমার মনে হয় আমি শেষ পর্যন্ত এটি শক্ত হয়ে গিয়েছি।

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 বাইট ব্লককে স্ট্রিংয়ের চেয়ে মাইএসকিএলে আরও দক্ষ হওয়া উচিত। আমি যাইহোক এটি খারাপ হতে আশা করব না।

একটি অসুবিধা যা আমি পেয়েছি তা হল কমপক্ষে ফাইপাইম্যাডমিনে আপনি রেকর্ডগুলি সম্পাদনা করতে পারবেন না কারণ এটি স্পষ্টত "টেবিল থেকে আইডি = ..." নির্বাচন করুন এবং বিবিধ ডিসপ্লে সমস্যা রয়েছে এমন জন্য কিছু ধরণের চরিত্র রূপান্তর করার চেষ্টা করে।

এটি ব্যতীত সবকিছু ঠিকঠাক বলে মনে হচ্ছে এবং তাই আমি এটি এখানে ফেলে দিচ্ছি। আপনি যদি এর সাথে একটি সুস্পষ্ট ত্রুটি দেখতে পান তবে একটি মন্তব্য করুন। আমি এর উন্নতির জন্য কোন পরামর্শ স্বাগত জানাই।

যদি আমি কিছু হারিয়ে না দিই তবে উপরের সমাধানটি কাজ করবে যদি অন্তর্নিহিত ডাটাবেসের কোনও ইউআইডি টাইপ থাকে। যদি এটি না হয়, সারণীটি তৈরি হওয়ার সময় আপনি সম্ভবত ত্রুটিগুলি পেতে পারেন। আমি যে সমাধানটি নিয়ে এসেছি আমি মূলত এমএসএসকিএল সার্ভারকে টার্গেট করছিলাম এবং তারপরে শেষ পর্যন্ত মাইএসকিউএল চলে এসেছি, তাই আমি মনে করি যে আমার সমাধানটি আরও বেশি নমনীয় বলে মনে হচ্ছে এটি মাইএসকিএল এবং স্ক্লাইটে কাজ করে fine পোস্টগ্রাগেস এখনও চেক করতে বিরক্ত করেননি।


হ্যাঁ, আমি যাকোবের উত্তর থেকে রেফারেলগুলি দেখে এটি পোস্ট করেছি।
টম উইলিস

4
মনে রাখবেন যে আপনি যদি 0.6 বা তার বেশি সংস্করণ ব্যবহার করছেন তবে টমের সমাধানে এমএসবাইনারি আমদানি বিবৃতিটি "স্কেলচেমি.ডায়ালিক্স থেকে। সূত্র: mail-archive.com/sqlalchemy@googlegroups.com/msg18397.html
Cal জ্যাকবসন

4
"আমি এটি লিখেছি" একটি মৃত লিঙ্ক।
জুলেক্স


4
@ কোডেনইঞ্জা পোস্টগ্রেস্কেলের ইতিমধ্যে একটি নেটিভ ইউআইডি টাইপ রয়েছে, তাই কেবল sqlalchemy.dialects.postgresql.UUIDসরাসরি ব্যবহার করুন । দেখতে ব্যাক-এন্ড-অজ্ঞেয়বাদী GUID প্রকার
cowbert

24

আপনি যদি 'স্ট্রিং' কলামে ইউইউডিউ মান সহ খুশি হন তবে এখানে একটি সহজ সমাধান পাওয়া যায়:

def generate_uuid():
    return str(uuid.uuid4())

class MyTable(Base):
    __tablename__ = 'my_table'

    uuid = Column(String, name="uuid", primary_key=True, default=generate_uuid)

4
আপনি যদি সত্যই অদ্ভুত ডাটাবেস না ব্যবহার করেন যা এগুলিকে সমর্থন করে না আপনি স্ট্রিং হিসাবে ইউআইডি সংরক্ষণ করবেন না। অন্যথায়, আপনার সমস্ত ডেটা স্ট্রিং হিসাবে সংরক্ষণ করুন ...;)
নিক

@ নিক কেন? খারাপ কি?
রাইপস

6
@ অ্যারেপ্পস - অনেকগুলি ডাউনসাইড রয়েছে - মনের শীর্ষ থেকে কিছু দূরে: আকার - স্ট্রিং ইউইড দ্বিগুণ স্থান গ্রহণ করে - 16 বাইটস বনাম 32 অক্ষর - কোনও বিন্যাস সহ নয়। প্রসেসিংয়ের সময় - আপনার ডেটাসেটটি বড় হওয়ার সাথে সাথে আরও বাইটস = আরও প্রসেসিং সময় সিপিইউ দ্বারা by uuid স্ট্রিং ফর্ম্যাটগুলি ভাষা দ্বারা পৃথক হয়, সংযোজন প্রয়োজনীয় অনুবাদ যুক্ত করে। কারও পক্ষে কলামটির অপব্যবহার করা সহজ, কারণ আপনি সেখানে যে কোনও কিছু রাখতে পারেন, যেগুলি জিনিসগুলি নয়। এটি শুরু করার জন্য যথেষ্ট হওয়া উচিত।
নিক

পারফরম্যান্স সমস্যার জন্য আপনার স্ট্রিংগুলি কোনও ইউইডির জন্য কলাম হিসাবে ব্যবহার করা উচিত নয়। একটি বাইনারি (16) আরও প্রস্তাবিত।
সিরিল এন।

19

আমি 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?
ওয়াল্টার

4
SQLAlchemy-Utilsএকটি তৃতীয় পক্ষের প্যাকেজ, আপনাকে প্রথমে এটি ইনস্টল করতে হবে:pip install sqlalchemy-utils
বেরিসালভ লোপাক

আপনার মাইগ্রেশনগুলিতে অ্যাকাউন্ট করা বা ইউইউডের জন্য ইউএইউডি বনাম CHAR / BINARY মান থাকা সিস্টেমগুলি থাকা দরকার তবে এটি way
rjurney

9

যেহেতু আপনি পোস্টগ্রিজ ব্যবহার করছেন এটি কাজ করা উচিত:

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)

4
পোস্টগ্র্রেএসকিউএল ডাটাবেস ব্যবহার করে সেই বিকাশকারীদের পক্ষে এটিই কেবল গ্রহণযোগ্য উত্তর হওয়া উচিত।
হোসে এল প্যাটিয়ো

5

এখানে এসকিউএএলএলচেমি ডক্স থেকে ব্যাকএন্ড অ্যাগনোস্টিক জিইউইডের উপর ভিত্তি করে একটি পদ্ধতির কথা রয়েছে , তবে ইউআইডিগুলিকে পোস্ট-পোস্টস্ক্রাকল ডাটাবেসে সংরক্ষণ করার জন্য বিনয়ের ক্ষেত্র ব্যবহার করে।

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)

4
এর ব্যবহার কী হবে?
কোডট্রোপার

3

যদি কেউ আগ্রহী হয় তবে আমি টম উইলিস উত্তরটি ব্যবহার করছি, তবে ইউইডিতে একটি স্ট্রিং যুক্ত করতে দরকারী বলে মনে করেছি। প্রক্রিয়া_বিন্দ_প্যারাম পদ্ধতিতে ইউআইডি রূপান্তর

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

-19

আপনি একটি কাস্টম প্রকার লেখার চেষ্টা করতে পারেন , উদাহরণস্বরূপ:

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। না হয় পদ্ধতির কি অন্যের তুলনায় কোনও সুবিধা বা অসুবিধা রয়েছে?
জ্যাকব গ্যাব্রিয়েলসন

11
এটি এমনকি কাজ করে না, ডক্স থেকে ডামি টাইপের উদাহরণ থেকে এটি কেবল কাটা-পেস্টের কাজ। টম উইলিসের নীচের উত্তরটি আরও ভাল।
জেসি ill

এটির কি দরকার নেই default=?? উদাহরণস্বরূপColumn('id', UUID(), primary_key=True, default=<someautouuidgeneratingthing>)
আইজেমস 13'16

"পৃষ্ঠায় পাওয়া যায় নি" লিঙ্ক পয়েন্টগুলি, ডকস.সক্লালচিমি.অর্গ /
//
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.