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()
는 Person
과 Company
인스턴스를 반환합니다. Contact
가 PolyModel
대신 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()
에서 반환되는 클래스 이름은 서브클래스에서 고유해야 합니다.