2011-10-05 13 views
5

मैं एक कॉलम नाम बदलने की कोशिश कर रहा हूं। पहला प्रयास इस स्क्रिप्ट के साथ किया गया था:sqlalchemy-migrate के साथ कॉलम नाम माइग्रेशन को कैसे बदलें?

meta = MetaData() 

users = Table('users', meta, 
    Column('id', Integer, primary_key=True), 
    Column('name', String(50), unique=True), 
    Column('email', String(120), unique=True) 
    ) 

def upgrade(migrate_engine): 
    meta.bind = migrate_engine 
    users.c.id.alter(name='id') 

def downgrade(migrate_engine): 
    meta.bind = migrate_engine 
    users.c.id.alter(name='user_id') 

मेरी देव डेटाबेस (SQLite) काम करता है पर migrate.py test चल रहा है और इतने उन्नयन और पदावनति करता है। लेकिन जब इसे हेरोकू पर मेरे परीक्षण वातावरण में तैनात किया जाता है (जहां PostgreSQL 8.3 का उपयोग किया जाता है) जब मैं अपग्रेड करने का प्रयास करता हूं तो मुझे एक ट्रेस मिलता है।

sqlalchemy.exc.ProgrammingError: (ProgrammingError) column "id" does not exist 

मैं तो अपग्रेड विधि में users.c.user_id का उपयोग करने की कोशिश की: सार यह संदेश है।

meta_old = MetaData() 
meta_new = MetaData() 

users_old = Table('users', meta_old, 
    Column('user_id', Integer, primary_key=True), 
    Column('name', String(50), unique=True), 
    Column('email', String(120), unique=True) 
    ) 

users_new = Table('users', meta_new, 
    Column('id', Integer, primary_key=True), 
    Column('name', String(50), unique=True), 
    Column('email', String(120), unique=True) 
    ) 

def upgrade(migrate_engine): 
    meta_old.bind = migrate_engine 
    users_old.c.user_id.alter(name='id') 

def downgrade(migrate_engine): 
    meta_new.bind = migrate_engine 
    users_new.c.id.alter(name='user_id') 

यह पहले से ही SQLAlchemy-विस्थापित लिपियों के लिए मॉडल कॉपी-पेस्ट करने के लिए अभ्यास की सिफारिश की है: यह दोनों परिवेशों .:

AttributeError: user_id 

वैकल्पिक हल अब मैं उपयोग कर रहा हूँ में विफल रहता है इस स्क्रिप्ट है। लेकिन यह अतिरिक्त डुप्लिकेशंस मेरे लिए थोड़ा अधिक हो जाता है। कोई भी जानता है कि यह कैसे किया जाना चाहिए। मान लीजिए कि यह एक बग है, मैं कुछ कामकाज को कम करने के सुझावों पर सुझाव देना चाहता हूं।

उत्तर

12

बाहर निकलता है यहां तक ​​कि एक डीआरवाई: एर समाधान है जिसकी मैंने आशा की थी। आत्मनिरीक्षण! इस तरह:

def upgrade(migrate_engine): 
    meta = MetaData(bind=migrate_engine) 
    users = Table('users', meta, autoload=True) 
    users.c.user_id.alter(name='id') 

def downgrade(migrate_engine): 
    meta = MetaData(bind=migrate_engine) 
    users = Table('users', meta, autoload=True) 
    users.c.id.alter(name='user_id') 

एक आकर्षण की तरह काम करता है!

+2

अच्छा, हालांकि मैं स्कीमा माइग्रेशन में autoload = True का उपयोग करने से सावधान हूं। बस भविष्य में एक सिर-अप, डाउनग्रेड में अपने परिवर्तनों को विपरीत में लागू करना याद रखें! यदि आप नहीं करते हैं, तो आप (शायद) बहुत सारी त्रुटियां प्राप्त करेंगे! –

1

मुझे लगता है कि यह किसी भी SQL उत्पन्न नहीं कर सकता क्योंकि आपका मेटाडेटा संदर्भ मिश्रित हो रहा है। आप अपने Table कक्षाओं में दो अलग मेटाडेटा ऑब्जेक्ट्स का उपयोग कर रहे हैं, और यह वास्तव में अच्छा नहीं है। आपको केवल एक की जरूरत है। मेटाडेटा ऑब्जेक्ट्स के स्टेल-नेस को ट्रैक करता है, चाहे उसे ऑब्जेक्ट अपडेट, विदेशी कुंजी बाधाओं आदि के लिए प्रश्न जारी करने की आवश्यकता हो और इसे आपके सभी तालिकाओं और रिश्तों के बारे में जानना आवश्यक है।

एक MetaData ऑब्जेक्ट का उपयोग करने के लिए बदलें, और echo=True को अपने sqlalchemy.create_engine कॉल पर पास करें और यह SQL आउटपुट प्रिंट करेगा जो यह मानक आउटपुट के लिए उपयोग कर रहा है। Postgres के लिए एक ही भूमिका (उपयोगकर्ता) के रूप में लॉग इन करते समय स्वयं को उस क्वेरी को निष्पादित करने का प्रयास करें। आप पाते हैं कि यह एक साधारण अनुमति समस्या है।

कॉपी-पेस्टिंग के संबंध में: मुझे लगता है कि Django के पास Table और उनके मॉड्यूल में घोषणात्मक कक्षाएं रखने और उन्हें आयात करने का एक अच्छा सम्मेलन है। हालांकि, क्योंकि आपको MetaData ऑब्जेक्ट को Table फैक्ट्री में पास करना होगा, जो मामलों को जटिल करता है। आप सिंगलटन/ग्लोबल मेटाडाटा ऑब्जेक्ट का उपयोग कर सकते हैं, या केवल घोषणात्मक में परिवर्तित कर सकते हैं।

थोड़ी देर के लिए मैंने एक-तर्क फ़ंक्शन को कार्यान्वित करना चुना जो Table ऑब्जेक्ट्स को मेटाडेटा दिया गया और परिणाम कैश किया - असल में एक सिंगलटन मॉडल क्लास को कार्यान्वित करना। तब मैंने फैसला किया कि मूर्खतापूर्ण और घोषित करने के लिए स्विच किया गया था।

+0

मुझे पता है कि यह दो मेटाडाटा वस्तुओं का उपयोग करना एक अच्छी आदत नहीं है। लेकिन यह स्क्रिप्ट काम करने के लिए केवल कामकाज है। यह पहली स्क्रिप्ट है जो काम नहीं करती है। ट्रेस में SQL कथन शामिल है और यह गलत नाम से कॉलम को बदलने का प्रयास कर रहा है। उस गूंज = सच के बारे में जानना अच्छा है, यह आसान हो जाएगा! – PEZ

+0

कॉपी-पेस्टिंग के बारे में नहीं। स्क्लेल्चेमी-माइग्रेट यूएसर गाइड से यह सलाह है: http://packages.python.org/sqlalchemy-migrate/versioning।एचटीएमएल # लेखन-स्क्रिप्ट-साथ-लगातार-व्यवहार मुझे पता नहीं चला है कि स्क्लेल्चेमी-माइग्रेट के साथ घोषणात्मक का उपयोग कैसे करें। क्या यह संभव है? – PEZ

+0

मैंने कोशिश नहीं की है। सौभाग्य! – wberry

2

यह एक भी काम करता है:

from alembic import op 
.... 
def upgrade(migrate_engine): 
    op.alter_column('users', 'user_id', new_column_name='id') 

def downgrade(migrate_engine): 
    op.alter_column('users', 'id', new_column_name='user_id') 
संबंधित मुद्दे