2015-01-16 2 views
3

내 연구 프로젝트에 대해 장고를 ORM으로 만들고 있습니다. 기존 ORM을 사용할 수 없기 때문에 장고를 직접 작성해야합니다. 나 자신을 교육하기 위해 나는 장고에서와 같은 ORM이 좋을 것이라고 생각했다.Django-model-like 메타 클래스 트릭을 수행하는 방법

ORM에서는 장고에서 구현 된 것과 동일한 스타일로 모델 정의를 작성하지 않았습니다. 즉.

class Person(models.Model): 
    first_name = models.CharField(max_length=30) 
    last_name = models.CharField(max_length=30) 

장고는 메타 클래스를 사용하여 내 프로젝트에 나도 사용하고 있습니다,하지만 난 메타 클래스는 클래스하지 인스턴스와를 구성한다는 사실에 문제가 있으므로 모든 속성은 클래스 속성과 모든 인스턴스간에 공유됩니다.

내가 시도했지만 때문에 앞서 말한 어떤 일반적인 예, 그것은 작동하지 않습니다 : 나는 Djangos 소스에서 조회하려고

def getmethod(attrname): 
    def _getmethod(self): 
     return getattr(self, "__"+attrname).get() 
    return _getmethod 

def setmethod(attrname): 
    def _setmethod(self, value): 
     return getattr(self, "__"+attrname).set(value) 
    return _setmethod 

class Metaclass(type): 
    def __new__(cls, name, based, attrs): 
     ndict = {} 
     for attr in attrs: 
      if isinstance(attrs[attr], Field): 
       ndict['__'+attr] = attrs[attr] 
       ndict[attr] = property(getmethod(attr), setmethod(attr)) 
     return super(Metaclass, cls).__new__(cls, name, based, ndict) 


class Field: 
    def __init__(self): 
     self.value = 0; 

    def set(self, value): 
     self.value = value 

    def get(self): 
     return self.value 

class Mainclass: 
    __metaclass__ = Metaclass 

class Childclass(Mainclass): 
    attr1 = Field() 
    attr2 = Field() 


a = Childclass() 
print "a, should be 0:", a.attr1 
a.attr1 = "test" 
print "a, should be test:", a.attr1 

b = Childclass() 

print "b, should be 0:", b.attr1 

하지만 나를 이해하기가 너무 복잡하다 "마술"은 어딘가에 숨어있는 것 같습니다.

질문은 간단합니다. 어떻게 장고가 매우 단순화 된 예제에서 이렇게합니까?

답변

3

답변은 올바른 코드를 확인한 후에 매우 간단합니다. Django에서 사용하는 메타 클래스는 모든 필드를 <model>._meta.fields (잘, 다소)에 추가하지만 실제 클래스에서 필드 속성이 제거됩니다. 이것에 대한 유일한 예외는 RelatedField 하위 클래스입니다.이 경우 객체 설명자가 추가됩니다 (속성과 유사합니다. 실제로는 고유가 객체 구현자인 객체 설명 자입니다).

그런 다음, 모델의 __init__ 방법, 모든 필드를 통해 코드를 반복하고, 하나 *args 또는 **kwargs에서 제공하는 값을 설정하거나, 인스턴스에 기본값 을 설정합니다. 당신의 예에서

,이 클래스 Personfirst_namelast_name라는 이름의 속성을하지 않아도된다는 것을 의미하지만, 두 필드는 Person._meta.fields에 저장됩니다. 그러나 Person의 인스턴스는 인수로 제공되지 않더라도 항상 first_namelast_name이라는 속성을 갖습니다.

관련 문제