2017-10-13 1 views
3

私は、ORMが明示的にテーブル名とカラム名を指定せずにクラス属性を使ってテーブルのカラムを解決する方法を理解しようとしています。ORMモデル定義は列属性を実際の列にどのようにバインドしますか?

from orm import Column 

class Car(Model): 
    id = Column() 

クエリは、これを実行することができます:

Car.select().where(Car.id == 7) 

私は列が__eq__オペレータのための方法を定義していますが、どのように列のインスタンスは、それがクラスCarと属性idを参照している知っているだろうことを理解します(これらはデフォルトでテーブル名とカラム名に使用されているものとします)?

私は、ORMのlibsの仕組みを掘り下げて、Pythonについて多くのことを学んでいます!

答えて

2

基本クラス(Model)は、メタクラスまたはイントロスペクションを実行するファクトリメソッド(__new__など)と関連しています。ここで

は、関数(簡単な解決策)を再現することができる方法である:それは空またはNoneある場合

class Model(): 
    pass 


class Column(): 
    def __init__(self, name=None): 
     self.name = name 


def setup_class(cls): 
    for name, value in cls.__dict__.items(): 
     if isinstance(value, Column): 
      attr = getattr(cls, name) 
      attr.name = attr.name or name 

このsetup_class機能は、例えば、CLSクラスおよびセットアップ属性をイントロスペクト:

class Car(Model): 
    id = Column() 


from pprint import pprint 
pprint(Car.id.name) 
# -> None 

setup_class(Car) 
pprint(Car.id.name) 
# -> 'id' 

編集

メタクラス使用

実装例:もちろん

class Column(): 
    def __init__(self, name=None): 
     self.name = name 


class MyMeta(type): 
    def __new__(cls, name, bases, attrs): 
     for name, col in attrs.items(): 
      if isinstance(col, Column): 
       col.name = col.name or name 
     return super(MyMeta, cls).__new__(cls, name, bases, attrs) 


class Model(metaclass=MyMeta): 
    pass 


class Car(Model): 
    id = Column() 


import pprint 
pprint.pprint(Car.id.name) 
# -> 'id' 

を、それは十分ではありません。 Columndescriptorであることを理解する必要があります。この記述子は、SQLクエリを構築するために使用されます。

+0

私はいくつかの魔法が不足していることを知っていました。前にメタクラスに遭遇したことはありませんでした。ありがとうLaurent! – pybot

関連する問題