SQLAlchemy sürüm oluşturma, sınıf içe aktarma sırasını önemser

| | | | | | | | | |

Buradaki kılavuzu izliyordum:

http ://www.sqlalchemy.org/docs/orm/examples.html?highlight=versioning#versioned-objects

ve bir sorunla karşılaştınız. İlişkilerimi şu şekilde tanımladım:

generic_ticker = Relations("MyClass", backref=backref("stuffs")) 

dizelerle, yani "Model modüllerimin içe aktarma sırasını umursamıyorum. Bunların hepsi normal şekilde çalışıyor, ancak sürüm oluşturma metasını kullandığımda şu hatayı alıyorum:

sqlalchemy.exc.InvalidRequestError: Eşleştiriciyi başlatırken Mapper|MyClass|stuffs, "Tüccar" ifadesi bir ad bulamadı ("Sınıfım" adı tanımlı değil"). Bu bir sınıf adıysa, her iki bağımlı sınıf tanımlandıktan sonra bu ilişkiyi() sınıfa eklemeyi düşünün .

Hatanın izini şurada buldum:

 Dosya "/home/nick/workspace/gm3/gm3/lib/history_meta.py", satır 90, __init__ mapper = class_mapper(cls) Dosyasında "/home/nick/venv/tg2env/lib/python2.6/site-packages/sqlalchemy/orm/util.py", satır 622, class_mapper mapper = mapper.compile () 

class VersionedMeta(DeclarativeMeta): def __init__(cls, cl assname, bases, dict_): DeclarativeMeta.__init__(cls, classname, bases, dict_) deneyin: mapper = class_mapper(cls) _history_mapper(mapper) hariç UnmappedClassError: pass 

Sorunu düzelttim try: bir lambda'daki şeyler hariç ve tüm ithalatlar gerçekleştikten sonra hepsini çalıştırarak. Bu işe yarıyor ama biraz saçma görünüyor, bunun nasıl düzeltileceğine dair herhangi bir fikir daha iyi bir yol mu?

Teşekkürler!

Güncelleme

Sorun aslında ithalat siparişi ile ilgili değil. Sürüm oluşturma örneği, eşleyicinin sürümlendirilmiş her sınıfın oluşturucusunda derlenmesini gerektirecek şekilde tasarlanmıştır. Ve ilgili sınıflar henüz tanımlanmadığında derleme başarısız olur. Döngüsel ilişkiler durumunda, eşlenen sınıfların tanım sırasını değiştirerek onu çalıştırmanın bir yolu yoktur.

Güncelleme 2

Yukarıdaki güncellemede belirtildiği gibi ( Burada başkalarının gönderilerini düzenleyebileceğinizi bilmiyordum :)) bunun nedeni büyük olasılıkla döngüsel referanslardır. Bu durumda birisi hackimi faydalı bulabilir (bunu turbogears ile kullanıyorum) (VersionedMeta'yı değiştirin ve history_meta'da create_mappers global ekleyin)

create_mappers = [] class VersionedMeta(DeclarativeMeta) : def __init__(cls, classname, bases, dict_): DeclarativeMeta.__init__(cls, classname, bases, dict_) #Bu kodu çökerken ekledim, aksi halde def make_mapper(): deneyin: mapper = class_mapper(cls) _history_mapper (mapper) hariç UnmappedClassError: pass create_mappers.append(lambda: make_mapper()) 

Ardından modellerinizde aşağıdaki gibi bir şey yapabilirsiniz __init__.py

# Model modüllerinizi buradan içe aktarın myproj.lib.history_meta'dan create_mappers'ı myproj.model.misc'den içe aktarın * myproj.model.stuff import * #setup geçmişi [func() for create_mappers] 

Bu şekilde yalnızca eşleştiricileri oluşturur tüm sınıflar tanımlandıktan sonra.

Güncelleme 3 Biraz alakasız ama bazı durumlarda yinelenen bir birincil anahtar hatasıyla karşılaştım (tek seferde aynı nesnede 2 değişiklik yapmak) . Geçici çözümüm, yeni bir birincil otomatik artan anahtar eklemek oldu. Tabii ki mysql ile 1'den fazla olamaz, bu yüzden geçmiş tablosunu oluşturmak için kullanılan mevcut öğelerin birincil anahtarını kaldırmak zorunda kaldım. Genel koduma göz atın (bir hist_id ve yabancı anahtar kısıtlamasından kurtulmak dahil):

"""sqlalchemy.ext.declarative'den """ resmi sqlalchemy reppies'ten çalındı sqlalchemy.orm'dan DeclarativeMeta import mapper, class_mapper, öznitelikler, sqlalchemy.orm.exc'den object_mapper import UnmappedClassError, UnmappedColumnError from sqlalchemy import Table, Column, ForeignKeyConstraint, Integer from sqlalchemy.orm.interfaces import SessionExtension from sqlalchemy.orm.properties import RelationshipProperty from sqlalchemy.types import DateTime import datecolsion sqlalchemy.orm. : col.foreign_keys'de fk için: if fk.references(table): return True return False def _history_mapper(local_mapper): cls = local_mapper.class_ # "active_history" bayrağını # sütun eşlemeli a üzerinde ayarlayın ttributes, bilginin eski sürümünün her zaman local_mapper.iterate_properties dosyasında yüklenmesini (şu anda tüm özniteliklerde ayarlar): getattr(local_mapper.class_, prop.key).impl.active_history = True super_mapper = local_mapper.inherits super_history_mapper = getattr(cls, "__history_mapper__", Yok) polymorphic_on = Yok super_fks = [] super_mapper değilse veya local_mapper.local_table super_mapper.local_table değilse: cols = [] local_mapper.local_table.c içindeki sütun için: if column.name == "version": devam col = column.copy() col.unique = False #don"t öğeleri normal db'den otomatik artırma, eğer col.autoincrement: col.autoincrement = False #sqllite, col.primary_key ise bileşik anahtar: col.primary_key = super_mapper ve col_references_table ise False(sütun, super_mapper.local_table): super_fks.append((col.key, list(super_history_mapper.base_mapper.local_table.primary_key)[0])) sütunlar. Sütun local_mapper.polymorphi ise append(col) c_on: polymorphic_on = col #if super_mapper: # super_fks.append(("sürüm", super_history_mapper.base_mapper.local_table.c.version)) cols.append(Column("hist_id", Tamsayı, birincil_key=Doğru, otomatik artırma=Doğru) ) cols.append(Column("version", Integer)) cols.append(Column("changed", DateTime, default=datetime.datetime.now)) if super_fks: cols.append(ForeignKeyConstraint(*zip(*super_fks)) )) tablo = Tablo(local_mapper.local_table.name + "_history", local_mapper.local_table.metadata, *cols, mysql_engine="InnoDB") başka: # tek tablo mirası. # eklenmiş olabilecek ek sütunları alın ve bunları geçmiş tablosuna ekleyin. local_mapper.local_table.c'deki sütun için: eğer column.key super_history_mapper.local_table.c'de değilse: col = column.copy() super_history_mapper.local_table.append_column(col) tablo = Yok eğer super_history_mapper: bases = (super_history_mapper.class_,) else: bases = local_mapper.base_mapper.class_.__bases__ versioned_cls = type.__new__(type, "%sHistory" % cls.__name__, bases, {}) m = mapper( versioned_cls, tablo, inherits=super_history_mapper, polymorphic_on=polymorphic_identity, polymorphic_identity, =local_mapper.polymorphic_identity ) cls.__history_mapper__ = super_history_mapper değilse m: cls.version = Column("version", Integer, default=1, nullable=False) create_mappers = [] class VersionedMeta(DeclarativeMeta): def __init__(cls , bases, dict_): DeclarativeMeta.__init__(cls, classname, bases, dict_) #Bu kodu çökerken ekledim, aksi halde def make_mapper(): deneyin: mapper = class_mapper(cls) _history_mapper(mapper) hariç UnmappedClassError: pass create_mappers.append(lambda: make_mapper()) def versioned_objects(iter): iter içindeki nesne için: if hasattr(obj, "__history_mapper__"): verim nesnesi def create_version(obj, session, delete = False): obj_mapper = object_mapper(obj) history_mapper = obj.__history_mapper__ history_cls = history_mapper.class_ obj_state = öznitelikler.instance_state(obj) attr = {} obj_changed = om, hm için yanlış zip(obj_mapper.iterate_to_root(), history_mapper.iterate_to_root()): hm.single: hm.single: hm'de hist_col için devam et .local_table.c: hist_col.key == "sürüm" veya hist_col.key == "değişti" veya hist_col.key == "hist_id" ise: devam obj_col = om.local_table.c[hist_col.key] # değeri al # eşlenen sütunla ilgili MapperProperty'ye dayalı # özniteliği. bu, eşlenen sütununkinden farklı bir anahtar ada sahip olan MapperProperties # kullanımına izin verecektir. deneyin: prop = obj_mapper.get_property_by_column(obj_col) hariç UnmappedColumnError: # tek tablo mirası durumunda, eşlenen tabloda yalnızca alt sınıf için tasarlanmış # sütun olabilir. # temel sınıftaki alt sınıf sütununun "eşlenmemiş" durumu, sqla 0.5.2'den itibaren bildirim modülünün bir özelliğidir. devam # süresi dolmuş nesne öznitelikleri ve ayrıca ertelenmiş sütunlar # dict içinde olmayabilir. getattr() kullanarak ne olursa olsun yüklemeye zorlayın. prop.key obj_state.dict'te değilse: getattr(obj, prop.key) a, u, d = öznitelikler.get_history(obj, prop.key) if d: attr[hist_col.key] = d[0] obj_changed = True elif u: attr[hist_col.key] = u[0] else: # özniteliğin değeri yoksa. attr[hist_col.key] = a[0] obj_changed = obj_changed değilse doğru: # değişmedi, ancak ilişkilerimiz var. Tamam # obj_mapper.iterate_properties'de prop için bunları da kontrol edin: if isinstance(prop, RelationshipProperty) ve öznitelikler.get_history(obj, prop.key).has_changes(): obj_changed = Obj_changed ve silinmemişse gerçek break: return attr[" version"] = obj.version hist = anahtar için history_cls(), attr.iteritems() içindeki değer: setattr(hist, key, value) obj.version += 1 session.add(hist) class VersionedListener(SessionExtension): def Before_flush(self, session, flush_context, instances): versioned_objects(session.dirty) içindeki nesne için: versioned_objects(session.deleted) içindeki nesne için create_version(obj, session): create_version(obj, session, delete = True) 

Shop

Learn programming in R: courses

$

Best Python online courses for 2022

$

Best laptop for Fortnite

$

Best laptop for Excel

$

Best laptop for Solidworks

$

Best laptop for Roblox

$

Best computer for crypto mining

$

Best laptop for Sims 4

$

Latest questions

NUMPYNUMPY

psycopg2: insert multiple rows with one query

12 answers

NUMPYNUMPY

How to convert Nonetype to int or string?

12 answers

NUMPYNUMPY

How to specify multiple return types using type-hints

12 answers

NUMPYNUMPY

Javascript Error: IPython is not defined in JupyterLab

12 answers

News


Wiki

Python OpenCV | cv2.putText () method

numpy.arctan2 () in Python

Python | os.path.realpath () method

Python OpenCV | cv2.circle () method

Python OpenCV cv2.cvtColor () method

Python - Move item to the end of the list

time.perf_counter () function in Python

Check if one list is a subset of another in Python

Python os.path.join () method