PolyModel 클래스

PolyModel 클래스를 사용하면 애플리케이션에서 다형성 쿼리를 지원하는 모델을 표준 Model 클래스보다 유연한 방식으로 정의할 수 있습니다. PolyModel 클래스에서 생성된 쿼리에는 클래스 또는 해당 서브클래스의 인스턴스인 결과가 포함될 수 있습니다.

이 쿼리는 google.appengine.ext.ndb.polymodel에서 정의됩니다. 다음 예시는 PolyModel 클래스가 제공하는 유연성을 보여줍니다.

from google.appengine.ext import ndb
from google.appengine.ext.ndb import polymodel

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

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

class Company(Contact):
  name = ndb.StringProperty()
  fax_number = ndb.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.query():
  print 'Phone: %s\nAddress: %s\n\n' % (contact.phone_number, contact.address)

Contact.query()PersonCompany 인스턴스를 반환합니다. ContactPolyModel 대신 Model에서 파생되면 각 클래스의 kind가 달라지고 Contact.query()Contact의 적절한 서브클래스의 인스턴스를 반환하지 않게 됩니다.

Person 인스턴스만 검색하려면 Person.query()를 사용하세요. Contact.query(Contact.class_ == 'Person')를 사용해도 됩니다.

일반적인 Model 메서드 외에도 PolyModel에는 몇 가지 흥미로운 클래스 메서드가 있습니다.

  • _get_kind(): 루트 클래스의 이름입니다(예: Person._get_kind() == 'Contact'). 이 예시에서는 루트 클래스인 Contact가 (여기를 루트로 하는 전체 계층 구조에 대해) Datastore에서 사용되는 종류로 다른 이름을 사용하도록 이 메서드를 재정의할 수 있습니다.
  • _class_name(): 현재 클래스의 이름입니다(예: Person._class_name() == 'Person'). 이 예시에서는 리프 클래스인 Person이 클래스 키 및 클래스 이름과 다른 이름을 사용하도록 이 메서드를 재정의할 수 있습니다. 리프가 아닌 클래스도 이 메서드를 재정의할 수 있지만 주의할 점이 있습니다. 즉, 서브클래스도 이 메서드를 재정의해야 하며, 그렇지 않으면 모두 같은 클래스 이름을 사용하게 되므로 혼동이 발생할 수 있습니다.
  • _class_key(): 계층 구조를 지정하는 클래스 이름의 목록입니다. Person._class_key() == ['Contact', 'Person']을 예로 들 수 있습니다. 더 깊은 계층 구조의 경우 PolyModel과 현재 클래스 사이의 모든 베이스가 여기에 포함됩니다. 여기서 현재 클래스는 포함되지만 PolyModel 자체는 제외됩니다. class_ 속성의 값과 동일합니다. 데이터 저장소 이름은 'class'입니다.

클래스 이름이 class_ 속성에서 사용되고 이 속성은 각 서브클래스를 구분하는 데 사용되므로 _class_name()에서 반환되는 클래스 이름은 서브클래스에서 고유해야 합니다.