PolyModel 클래스

참고: 새로운 애플리케이션을 빌드하는 개발자는 NDB 클라이언트 라이브러리를 사용하는 것이 좋습니다. NDB 클라이언트 라이브러리는 이 클라이언트 라이브러리와 비교할 때 Memcache API를 통한 자동 항목 캐싱과 같은 여러 이점이 있습니다. 현재 이전 DB 클라이언트 라이브러리를 사용 중인 경우 DB에서 NDB로의 마이그레이션 가이드를 참조하세요.

PolyModel 클래스는 그 자체로 다른 데이터 모델 정의의 슈퍼클래스가 될 수 있는 데이터 모델 정의의 슈퍼클래스입니다. PolyModel 클래스에서 생성된 쿼리에는 클래스 또는 해당 서브클래스의 인스턴스인 결과가 포함될 수 있습니다.

PolyModelgoogle.appengine.ext.db.polymodel 모듈에서 제공됩니다.

PolyModel은 Model의 서브클래스이며 이 클래스에서 클래스와 인스턴스 메서드를 상속받습니다. PolyModel 클래스는 여러 Model 메서드를 재정의하지만 새로운 인터페이스 요소를 사용하지는 않습니다.

소개

데이터 모델을 분류 계층구조로 정의하면 유용한 경우가 많습니다. 이는 객체 데이터베이스가 하나의 객체 클래스를 다른 클래스의 서브클래스로 정의할 수 있는 것과 유사합니다. 이러한 데이터베이스는 상위 클래스의 객체를 대상으로 쿼리를 수행하고 결과에 서브클래스의 객체를 포함할 수 있습니다. App Engine Datastore는 기본적으로 이러한 종류의 쿼리를 지원하지 않지만 Python SDK에 포함된 메커니즘인 PolyModel 클래스를 사용하여 이를 구현할 수 있습니다.

PolyModel에서 파생된 모델 클래스는 다른 모델 클래스의 기본 클래스가 될 수 있습니다. all()gql() 메서드를 사용하여 이러한 클래스에 대해 생성된 쿼리는 결과에 서브클래스의 인스턴스를 포함할 수 있습니다.

서브클래스는 상위 클래스에 없는 새 속성을 정의할 수 있습니다. 하지만 서브클래스는 상위 클래스의 속성 정의를 재정의할 수 없습니다. 이렇게 하면 DuplicateProperty 오류가 발생합니다.

참고로, 항목 및 모델에서 가져온 간단한 다음 예를 살펴보세요. PolyModel 클래스가 google.appengine.ext.db.polymodel 패키지를 통해 제공되는 것을 확인할 수 있습니다.

from google.appengine.ext import db
from google.appengine.ext.db import polymodel

class Contact(polymodel.PolyModel):
    phone_number = db.PhoneNumberProperty()
    address = db.PostalAddressProperty()

class Person(Contact):
    first_name = db.StringProperty()
    last_name = db.StringProperty()
    mobile_number = db.PhoneNumberProperty()

class Company(Contact):
    name = db.StringProperty()
    fax_number = db.PhoneNumberProperty()

p = Person(phone_number='1-206-555-9234',
           address='123 First Ave., Seattle, WA, 98101',
           first_name='Alfred',
           last_name='Smith',
           mobile_number='1-206-555-0117')
p.put()

c = Company(phone_number='1-503-555-9123',
            address='P.O. Box 98765, Salem, OR, 97301',
            name='Data Solutions, LLC',
            fax_number='1-503-555-6622')
c.put()

for contact in Contact.all():
  # Returns both p and c.
  # ...

for person in Person.all():
  # Returns only p.
  # ...

다형성은 Datastore의 기본 기능이 아니며 PolyModel 클래스 자체에서 구현됩니다. PolyModel 서브클래스에서 생성되는 모든 항목이 같은 종류의 Datastore에 저장됩니다. 이때 종류는 루트 클래스 이름과 같습니다(예: Animal). 각 객체는 클래스 계층구조를 'class'라고 하는 항목의 멀티 값 속성으로 저장합니다. 앱이 PolyModel 클래스의 all() 또는 gql() 메서드를 사용하여 쿼리를 만들면 클래스 또는 모든 서브클래스에서 생성된 항목으로 결과를 제한하는 'class' 속성의 필터가 쿼리에 포함됩니다.

PolyModel은 항목 속성을 사용하여 클래스 정보를 저장하므로 다형성 쿼리의 색인은 'class' 속성을 수용해야 합니다. 묵시적 필터는 균등 필터이며 다른 속성의 일치 필터 및 비일치 필터와 결합할 수 있습니다.

참고: PolyModel은 전체 경로가 아닌 'class' 속성의 클래스 이름만 사용합니다. ABACB와 같이 이름이 같은 여러 노드를 사용하여 클래스 계층구조를 만들 수 있습니다. 이때 하나를 쿼리하면 둘 모두의 항목이 반환됩니다. 마찬가지로 ABC를 쿼리하는 것과 ACB를 쿼리하는 것은 기능적으로 동일합니다. 따라서 이름이 같은 여러 노드를 사용하여 단일 클래스 계층구조를 만들지 않는 것이 좋습니다.

PolyModel은 서브클래스에서 속성 모델 정의를 재정의하는 작업을 지원하지 않습니다. 서브클래스가 슈퍼클래스에 정의된 속성을 다시 정의하려고 할 경우 클래스 정의가 DuplicatePropertyError를 발생시킵니다.

PolyModel은 슈퍼클래스를 공유하는 여러 클래스에서 상속받는 것을 포함하여 다중 상속을 지원합니다('다이아몬드' 상속). 클래스 하나는 각각 동일한 속성의 속성 모델 정의를 정의하는 클래스 두 개에서 상속받을 수 없습니다. 이렇게 하면 DuplicatePropertyError가 발생합니다. 하지만 클래스 하나는 동일한 슈퍼클래스에서 동일한 속성 모델 정의를 상속받는 클래스 두 개에서 상속받을 수 있습니다.

PolyModelExpando와 달리 동적 속성을 지원하지 않습니다. ExpandoPolyModel에 상응하는 요소는 없습니다.

생성자

PolyModel 클래스의 생성자는 다음과 같이 정의됩니다.

class PolyModel(parent=None, key_name=None, **kwds)

다른 모델 클래스의 슈퍼클래스가 될 수 있으며 쿼리에 서브클래스의 인스턴스를 결과로 포함할 수 있는 모델 클래스입니다. Model과 마찬가지로 PolyModel 클래스는 데이터 항목의 종류를 정의하기 위해 서브클래스화되어야 합니다.

PolyModel은 Model의 서브클래스이며 해당 메서드를 상속받거나 재정의합니다.

인수

parent
새 항목의 상위 요소인 항목의 모델 인스턴스 또는 키 인스턴스입니다.
key_name

새 항목의 이름입니다. 이름은 기본 키에 포함됩니다. None인 경우 시스템에서 생성된 ID가 키에 사용됩니다.

key_name 값은 숫자로 시작해서는 안 되고 __*__ 형식이 아니어야 합니다. 애플리케이션이 사용자가 제출한 데이터(예: 이메일 주소)를 Datastore 항목 키 이름으로 사용하는 경우 이러한 요구사항을 충족하기 위해 애플리케이션이 먼저 'key:'과 같이 알려진 문자열을 접두사로 추가하여 값을 처리해야 합니다.

key_name은 ASCII 텍스트로 변환된 str 값이 있는 유니코드 문자열로 저장됩니다.

**kwds
인스턴스 속성의 초기 값이며 키워드 인수로 사용됩니다. 각 이름은 새 인스턴스의 속성과 일치하며, PolyModel 클래스에 정의된 고정 속성과 일치해야 합니다.

클래스 메서드

PolyModel 클래스는 Model 클래스에 정의되는 클래스 메서드 외에 다음과 같은 클래스 메서드도 제공합니다.

PolyModel.class_key()

클래스 이름과 클래스의 모든 상위 클래스 이름을 튜플로 반환합니다.

PolyModel.class_name()

클래스 이름을 반환합니다. Python 클래스의 이름이 변경되는 경우 클래스가 이 메서드를 재정의할 수 있지만 항목은 원래 클래스 이름을 계속 사용해야 합니다.