2011-04-20 23 views
6

मैं निम्नलिखित कथात्मक परिभाषा के साथ एक मेज है संभाल SQLAlchemy करता है:कैसे तालिका परिभाषा अद्वितीय बाधा

class Type(Base): 
    __tablename__ = 'Type' 
    id = Column(Integer, primary_key=True) 
    name = Column(String, unique = True) 
    def __init__(self, name): 
     self.name = name 

स्तंभ "नाम" के लिए एक अनूठा बाधा है, लेकिन मैं ऐसा करने में सक्षम हूँ

type1 = Type('name1') 
session.add(type1) 
type2 = Type(type1.name) 
session.add(type2) 

तो, जैसा कि देखा जा सकता है, अद्वितीय बाधा बिल्कुल जांच नहीं की गई है, क्योंकि मैंने सत्र 2 ऑब्जेक्ट्स को उसी नाम से जोड़ा है।

जब मैं session.commit() करता हूं, तो मुझे एक mysql त्रुटि मिलती है क्योंकि बाधा mysql तालिका में भी है।

क्या यह संभव है कि sqlalchemy मुझे पहले से बताता है कि मैं इसे नहीं बना सकता या पहचान नहीं सकता और उसी "नाम" कॉलम के साथ 2 प्रविष्टियां नहीं डालता? यदि नहीं, तो क्या मुझे सभी मौजूदा नामों को याद रखना चाहिए, इसलिए मैं ऑब्जेक्ट बनाने से पहले जांच कर सकता हूं कि वे मौजूद हैं या नहीं?

उत्तर

9

SQLAlechemy unqquness को संभाल नहीं करता है, क्योंकि यह अच्छा तरीका नहीं करना संभव है। यहां तक ​​कि यदि आप बनाए गए ऑब्जेक्ट्स का ट्रैक रखते हैं और/या जांचते हैं कि इस तरह के नाम वाले ऑब्जेक्ट में कोई रेस हालत है: अन्य प्रक्रिया में कोई भी आपके द्वारा अभी चेक किए गए नाम के साथ एक नई ऑब्जेक्ट डाल सकता है। एकमात्र समाधान सम्मिलन के बाद लॉक को जांचने और रिलीज़ करने से पहले पूरी तालिका को लॉक करना है (कुछ डेटाबेस ऐसे लॉकिंग का समर्थन करते हैं)।

+0

मैं केवल एक डेटा डालने करते रहेंगे, तो मुझे यकीन है कि ऐसा नहीं होता है बनाती हूँ। मेरा सवाल यह है कि कैसे sqlalchemy फ़ील्ड की विशिष्टता को नियंत्रित करता है – duduklein

+4

@ डुडुकलीन यह विशिष्टता को संभाल नहीं करता है। और मेरा जवाब बताता है क्यों। –

6

AFAIK, sqlalchemy अजगर व्यवहार में विशिष्टता बाधाओं को संभाल नहीं करता है। उन "अद्वितीय = सच" घोषणाओं केवल डेटाबेस स्तर तालिका की कमी लागू करने के लिए यदि आप एक SQLAlchemy आदेश का उपयोग कर तालिका बनाने, अर्थात

Type.__table__.create(engine) 

या कुछ इस तरह उपयोग किया जाता है, और उसके बाद ही। यदि आप किसी मौजूदा तालिका के विरुद्ध एक एसए मॉडल बनाते हैं जिसमें वास्तव में यह बाधा मौजूद नहीं है, तो ऐसा होगा जैसे यह अस्तित्व में नहीं है।

अपने विशिष्ट उपयोग के आधार पर, आप शायद की तरह

try: 
    existing = session.query(Type).filter_by(name='name1').one() 
    # do something with existing 
except: 
    newobj = Type('name1') 
    session.add(newobj) 

या एक संस्करण एक पैटर्न का उपयोग करना होगा, या आप बस mysql अपवाद को पकड़ने और वहाँ से उबरने के लिए होगा। sqlalchemy.orm.exc.NoResultFound और sqlalchemy.orm.exc.MultipleResultsFound

आप दूसरी होती है, तो क्या आप फिर भी खराब कर रहे हैं और नहीं करना चाहिए बदतर है, जब पहली अपवाद तब होता है कि वस्तु बनाने चाहिए:

1

.one() अपवाद के दो प्रकार फेंकता है।

try: 
    existing = session.query(Type).filter_by(name='name1').one() 
# do something with existing 
except NoResultFound: 
    newobj = Type('name1') 
    session.add(newobj) 
3

From the docs

class MyClass(Base): 
    __tablename__ = 'sometable' 
    __table_args__ = (
      ForeignKeyConstraint(['id'], ['remote_table.id']), 
      UniqueConstraint('foo'), 
      {'autoload':True} 
      ) 
संबंधित मुद्दे