2016-09-16 2 views
3

Django를 읽고 지금 작업하고 있습니다. 내가 아직도 혼란스러워하는 것들 중 하나는 우리가 장고에서 만드는 모델 클래스가 멤버 변수가 아닌 정적 변수로 만들어지는 이유입니다. 예를Django - 모델 클래스에서 선언 된 변수가 정적 인 이유

class Album(models.Model): 
    artist = models.CharField(max_length=128, unique=True) 
    title = models.CharField(max_length=128, unique=True) 
    genre = models.CharField(max_length=128, unique=True) 

    def __unicode__(self): 
     return self.name 

를 들어 나는 그러나 나는 아직도 장고 모델의 필드 변수가 정적 원하는 이유에 혼란 스러워요 파이썬에서 정적 및 인스턴스 변수를 설명 여기 this 페이지를 읽어?

+0

모델이 Pro Django의 3 장 (모델) Marty Alchin, Apress에 의해 작성된 방법에 대한 훌륭한 글이 있습니다. –

답변

6

장고는 metaclass을 사용하여 모델 클래스를 만듭니다. 클래스의 __init__() 메서드가 새 인스턴스를 만드는 것처럼 메타 클래스의 __new__() 메서드는 클래스 자체를 만듭니다. 클래스 본문에 정의 된 모든 변수, 함수, 속성 등은 __new__() 함수에 전달됩니다. 엄밀히 말하면 클래스 본문에 변수를 정의하면 정적/클래스 변수가 생성되지 않습니다. __new__() 함수가 변수를 받아서 클래스에 설정 한 경우에만 클래스/정적 변수가됩니다.

Django는 필드와 특별한 Meta 내부 클래스에 대해 사용자 정의 __new__() 메서드를 제공함으로써이 동작을 재정의합니다. Meta 내부 클래스의 옵션은 Options 인스턴스로 변환되며이 인스턴스는 Model.Meta이 아닌 Model._meta으로 저장됩니다. 마찬가지로 정의한 필드는 클래스/정적 변수가 아닌 Model._meta.fields에 저장됩니다.

귀하의 예에서 클래스 Album에는 artist 속성이 없습니다 : Album.artist은 단순히 AttributeError을 발생시킵니다. 이것은 메타 클래스가 필드를 클래스에서 Album._meta.fields으로 이동시키기 때문입니다. Album의 인스턴스에는 artists 속성이 있지만 필드는 필드가 아닙니다. 대신 필드와 관련된 데이터베이스 값입니다. __init__ 모델의 메서드는 self._meta.fields을 사용하여 __init__에 전달되는 값 또는 기본값이있는 특성을 채워 인스턴스 변수가 있는지 확인합니다.

클래스 변수 만 __new__ 메서드에 전달됩니다. 필드를 __init__ 안에 인스턴스 변수로 정의한다면 필드는 결코 Model._meta.fields으로 전달되지 않으며 Django는 단순히 필드에 대해 알지 못합니다. Album.artist에 액세스 할 수 있지만이 값은 관련 데이터베이스 값이 아닌 실제 필드 인스턴스가됩니다. 기본적으로 모델을 모델로 만드는 마법을 놓치게됩니다.

관련 문제