[英]Access parent object from sqlalchemy association_proxy creator
[英]SQLAlchemy: Multiple Inheritance with dynamic 'association_proxy' creator function
我目前正在嘗試使用SQLAlchemy創建以下數據庫模式(使用ext.declarative):
我有一個基類MyBaseClass
,它為我所有可公開訪問的類提供了一些常用功能,一個mixin類MetadataMixin
,它提供了從imdb查詢元數據並存儲它的功能。 MetadataMixin
子類的每個類都有一個字段persons
,它提供與Person
類實例的M:N關系,以及字段persons_roles
,它提供與對象(每個子類一個)的1:N關系,該關系將role
存儲為具體Person在子類的實例中播放。
這是我的代碼目前的縮寫版本:
from sqlalchemy import Column, Integer, Enum, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class MyBaseClass(object):
"""Base class for all publicly accessible classes"""
id = Column(Integer, primary_key=True)
class Person(MyBaseClass):
"""A Person"""
name = Column(Unicode)
movies = association_proxy('movie_roles', 'movie',
creator=lambda m: _PersonMovieRole(movie=m))
shows = association_proxy('show_roles', 'show',
creator=lambda s: _PersonShowRole(show=s=))
class _PersonMovieRole(Base):
"""Role for a Person in a Movie"""
__tablename__ = 'persons_movies'
id = Column(Integer, primary_key=True)
role = Column(Enum('none', 'actor', 'writer', 'director', 'producer'),
default='none')
person_id = Column(Integer, ForeignKey('persons.id'))
person = relationship('Person', backref='movie_roles')
movie_id = Column(Integer, ForeignKey('movies.id'))
movie = relationship('Movie', backref='persons_roles')
class _PersonShowRole(Base):
"""Role for a Person in a Show"""
__tablename__ = 'persons_shows'
id = Column(Integer, primary_key=True)
role = Column(Enum('none', 'actor', 'writer', 'director', 'producer'),
default='none')
person_id = Column(Integer, ForeignKey('persons.id'))
person = relationship('Person', backref='show_roles')
show_id = Column(Integer, ForeignKey('shows.id'))
show = relationship('Episode', backref='persons_roles')
class MetadataMixin(object):
"""Mixin class that provides metadata-fields and methods"""
# ...
persons = association_proxy('persons_roles', 'person',
creator= #...???...#)
class Movie(Base, MyBaseClass, MetadataMixin):
#....
pass
我要做的是為association_proxy
創建一個通用的creator
函數,創建PersonMovieRole或PersonShowRole對象,具體取決於添加Person
的具體實例的類。 我現在堅持的是,我不知道如何將調用類傳遞給創建者函數。 這是可能的,或者甚至可能更容易實現我想要完成的工作?
當你的persons
字段被定義時,你不可能真正知道它最終會成為什么類.Python占用類成員的現成字典並type.__new__
創建類(通過type.__new__
),但是當它發生時,那些成員是已完全定義。
因此,您需要直接向mixin提供所需的信息,並容忍它將在您的代碼中創建的小重復。 我選擇類似這個的界面:
class Movie(Base, MyBaseClass, MetadataMixin('Movie')):
pass
(您也不能使用MetadataMixin(Movie)
,原因完全相同: Movie
要求其基類在創建類時完全定義。
要實現這樣的“參數化類”,只需使用一個函數:
def MetadataMixin(cls_name):
"""Mixin class that provides metadata-fields and methods"""
person_role_cls_name = 'Person%sRole' % cls_name
person_role_cls = Base._decl_class_registry[person_role_cls_name]
class Mixin(object):
# ...
persons = association_proxy('persons_roles', 'person',
creator=person_role_cls)
return Mixin
這是有效的,因為我們在Base._decl_class_registry
查找的Base._decl_class_registry
- 從聲明性基礎下降的所有類的注冊表 - 不是最終類(例如Movie
),而是關聯對象(例如PersonMovieRole
)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.