2012-12-03 3 views
6

मेरे पास वर्तमान में एक कॉलम है जिसमें HTML मार्कअप है। उस मार्कअप के अंदर, एक टाइमस्टैम्प है जिसे मैं एक नए कॉलम में स्टोर करना चाहता हूं (इसलिए मैं इसके खिलाफ पूछताछ कर सकता हूं)। मेरा विचार एक एकल प्रवास में निम्न करने के लिए किया गया था:एक अलेम्बिक प्रवासन के अंदर SQLAlchemy ORM का उपयोग करना: मैं कैसे करूँ?

  1. डेटा
  2. उपयोग ORM एचटीएमएल मैं
  3. पार्स करने के लिए प्रत्येक पंक्ति के लिए की जरूरत है वापस खींचने के लिए के लिए एक नया, व्यर्थ स्तम्भ बनाएं
    1. एचटीएमएल पार्स टाइमस्टैम्प
    2. अद्यतन ORM वस्तु बाहर निकलने के लिए

लेकिन जब मैं अपना माइग्रेशन चलाने की कोशिश करता हूं, तो यह एक अनंत लूप में फंस जाता प्रतीत होता है।

import sqlalchemy as sa 


tip = sa.sql.table(
    'tip', 
    sa.sql.column('id', sa.Integer), 
    sa.sql.column('publication_date', sa.DateTime(timezone=True)), 
) 


def upgrade(): 
    mappings = [ 
     (x.id, _extract_publication_date(x.rendered_html)) 
     for x in Tip.query 
    ] 

    op.add_column('tip', sa.Column('publication_date', sa.DateTime(timezone=True))) 

    exp = sa.sql.case(value=tip.c.id, whens=(
     (op.inline_literal(id), op.inline_literal(publication_date)) 
     for id, publication_date in mappings.iteritems() 
    )) 

    op.execute(tip.update().values({'publication_date': exp})) 


def downgrade(): 
    op.drop_column('tip', 'publication_date') 
+0

आप कैसे जानते हैं कि यह एक अनंत लूप में फंस गया है? –

+1

यदि 'Tip.query' उसी सत्र का उपयोग 'ओपी' के रूप में नहीं कर रहा है, तो 'चयन' के साथ 'वैकल्पिक' एक के लिए प्रतीक्षा करने के लिए एक 'अटक' के साथ 2 लेनदेन होंगे। वैसे भी, मुझे लगता है कि 'एलेम्बिक अपग्रेड' के बाद मैन्युअल रूप से चलाने के लिए ओआरएम भाग को अपनी स्क्रिप्ट पर ले जाना क्लीनर है। – sayap

+0

@ एक्स-इस्टेंस मुझे नहीं पता कि यह एक अनंत लूप में फंस गया है। मैं ** डीओ ** जानता हूं कि आदेश कभी वापस नहीं आता है। –

उत्तर

1

टिप्पणियों से जारी रखें, तो आप कुछ इस तरह की कोशिश कर सकते हैं: यहाँ मैं अब तक क्या आपके पास यह है

connection = op.get_bind() 
Session = sa.orm.sessionmaker() 
session = Session(bind=connection) 
4

क्या मेरे लिए काम किया निम्न करके एक सत्र प्राप्त करने के लिए है:

def _extract_publication_date(html): 
    root = html5lib.parse(html, treebuilder='lxml', namespaceHTMLElements=False) 
    publication_date_string = root.xpath("//a/@data-datetime")[0] 
    return parse_date(publication_date) 


def _update_tip(tip): 
    tip.publication_date = _extract_publication_date(tip.rendered_html) 
    tip.save() 


def upgrade(): 
    op.add_column('tip', sa.Column('publication_date', sa.DateTime(timezone=True))) 
    tips = Tip.query.all() 
    map(tips, _update_tip) 


def downgrade(): 
    op.drop_column('tip', 'publication_date') 
+0

यह एक * प्रकार * मेरे लिए काम करता था, हालांकि त्रुटियां थीं कि मेरे मॉडल पहले ही सत्र में बंधे थे। – killthrush

4

@ वेलोची के जवाब का प्रयोग करके थोड़ा प्रयोग करने के बाद, मैंने एलेम्बिक के अंदर स्क्लक्लेमी का उपयोग करने के लिए निम्न पैटर्न की तरह कुछ तय किया। यह मेरे लिए महान काम किया है और शायद ओपी के प्रश्न के लिए एक सामान्य समाधान के रूप में सेवा कर सकता है:

from sqlalchemy.orm.session import Session 
from alembic import op 

def upgrade(): 
    # Attach a sqlalchemy Session to the env connection 
    session = Session(bind=op.get_bind()) 

    # Perform arbitrarily-complex ORM logic 
    instance1 = Model1(foo='bar') 
    instance2 = Model2(monkey='banana') 

    # Add models to Session so they're tracked 
    session.add(instance1) 
    session.add(instance2) 

def downgrade(): 
    # Attach a sqlalchemy Session to the env connection 
    session = Session(bind=op.get_bind()) 

    # Perform ORM logic in downgrade (e.g. clear tables) 
    session.query(Model2).delete() 
    session.query(Model1).delete() 

यह दृष्टिकोण लेनदेन ठीक से संभाल प्रतीत होता है। इस पर काम करते समय, मैं डीबी अपवाद उत्पन्न करता हूं और वे चीजों को वापस अपेक्षित रूप से रोल करेंगे।

+1

यह ध्यान देने योग्य है कि यदि आपके मॉडल अक्सर बदल रहे हैं तो इस तकनीक को खराब सलाह दी जा सकती है। जब मॉडल बदलते हैं, तो यह पुराने माइग्रेशन को तोड़ सकता है जो मानते हैं कि मॉडल का एक निश्चित आकार है। – killthrush

संबंधित मुद्दे