2012-12-03 14 views
6

Şu anda HTML işaretlemesi içeren bir sütuna sahibim. Bu işaretlemenin içinde, yeni bir sütunda saklamak istediğim bir zaman damgası var (bu yüzden buna karşı sorgulayabiliyorum). Benim fikrim Tek bir taşıma aşağıdaki işlemleri yapmak üzere idi: Ben her satır için SQLalchemy ORM'yi Alembic migrasyon içinde kullanma: nasıl yapabilirim?

  • ayrıştırmak gerekiyor HTML geri çekmeye veri
  • Kullanım ORM için yeni, null sütunu oluşturun

      1. damgası
      2. güncelleme ORM nesne çıkarmak için HTML ayrıştırmak

    Ancak, geçişimi çalıştırmaya çalıştığımda sonsuz bir döngüde kalıyormuş gibi görünüyor. benim için çalıştı Ne

    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

    Bunun sonsuz bir döngüde sıkıştığını nereden biliyorsunuz? –

    +1

    Eğer 'Tip.query', 'op' ile aynı seansı kullanmıyorsa, 'SELECT' ile 'ALTER TABLE' birinin işlenmesini bekleyerek sıkışmış 2 işlem olacaktır. Her neyse, ORM bölümünü "alembic upgrade" den sonra elle çalıştırılmak için kendi betiğine taşımak daha temiz olduğunu düşünüyorum. – sayap

    +0

    @ X-Istence Biliyorum sonsuz bir döngüde sıkışmış. Ben ** DO komutunun asla geri dönmediğini biliyorum. –

    cevap

    1

    yorumlardan Devam böyle bir şey deneyebilirsiniz: İşte ben bugüne kadar bu var

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

    aşağıdakileri yaparak bir oturum elde etmektir:

    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

    Modellerimin zaten bir seansa bağlandığını söyleyen hatalar olsa da, bu bir * sort * benim için çalıştı. – killthrush

    4

    @ Velochy'nin yanıtını kullanarak biraz deneme yaptıktan sonra, Alembic içinde SqlAlchemy'ı kullanmak için aşağıdaki şablona benzer bir şeye yerleştim. Bu benim için çok çalıştı ve muhtemelen OP'ın soru için genel bir çözüm olarak hizmet verebilir:

    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() 
    

    Bu yaklaşım düzgün işlemleri işlemek için görünür. Sıklıkla bu konu üzerinde çalışırken, DB istisnaları üretecektim ve işleri beklendiği gibi geri çekeceklerdi.

    +1

    Modelleriniz sık sık değişiyorsa bu tekniğin yanlış anlaşılmayabileceğine dikkat edin. Modeller değiştiğinde, modellerin belirli bir şekli olduğunu varsayan eski geçişleri kırılabilir. – killthrush