thirdparty/google_appengine/google/appengine/ext/db/__init__.py
changeset 2864 2e0b0af889be
parent 2413 d0b7dac5325c
child 3031 7678f72140e6
equal deleted inserted replaced
2862:27971a13089f 2864:2e0b0af889be
   120 PostalAddress = datastore_types.PostalAddress
   120 PostalAddress = datastore_types.PostalAddress
   121 Rating = datastore_types.Rating
   121 Rating = datastore_types.Rating
   122 Text = datastore_types.Text
   122 Text = datastore_types.Text
   123 Blob = datastore_types.Blob
   123 Blob = datastore_types.Blob
   124 ByteString = datastore_types.ByteString
   124 ByteString = datastore_types.ByteString
       
   125 BlobKey = datastore_types.BlobKey
   125 
   126 
   126 _kind_map = {}
   127 _kind_map = {}
   127 
   128 
   128 
   129 
   129 _SELF_REFERENCE = object()
   130 _SELF_REFERENCE = object()
   184     GeoPt,
   185     GeoPt,
   185     IM,
   186     IM,
   186     PhoneNumber,
   187     PhoneNumber,
   187     PostalAddress,
   188     PostalAddress,
   188     Rating,
   189     Rating,
       
   190     BlobKey,
   189     ])
   191     ])
   190 
   192 
   191 _ALLOWED_EXPANDO_PROPERTY_TYPES = set(_ALLOWED_PROPERTY_TYPES)
   193 _ALLOWED_EXPANDO_PROPERTY_TYPES = set(_ALLOWED_PROPERTY_TYPES)
   192 _ALLOWED_EXPANDO_PROPERTY_TYPES.update((list, tuple, type(None)))
   194 _ALLOWED_EXPANDO_PROPERTY_TYPES.update((list, tuple, type(None)))
   193 
   195 
   239         "using a different name like %(attr_name)s_ and adding "
   241         "using a different name like %(attr_name)s_ and adding "
   240         "name='%(attr_name)s' to the parameter list of the property "
   242         "name='%(attr_name)s' to the parameter list of the property "
   241         "definition." % locals())
   243         "definition." % locals())
   242 
   244 
   243 
   245 
       
   246 def query_descendants(model_instance):
       
   247   """Returns a query for all the descendants of a model instance.
       
   248 
       
   249   Args:
       
   250     model_instance: Model instance to find the descendants of.
       
   251 
       
   252   Returns:
       
   253     Query that will retrieve all entities that have the given model instance
       
   254   as an ancestor. Unlike normal ancestor queries, this does not include the
       
   255   ancestor itself.
       
   256   """
       
   257 
       
   258   result = Query().ancestor(model_instance);
       
   259   result.filter(datastore_types._KEY_SPECIAL_PROPERTY + ' >',
       
   260                 model_instance.key());
       
   261   return result;
       
   262 
       
   263 
       
   264 def model_to_protobuf(model_instance, _entity_class=datastore.Entity):
       
   265   """Encodes a model instance as a protocol buffer.
       
   266 
       
   267   Args:
       
   268     model_instance: Model instance to encode.
       
   269   Returns:
       
   270     entity_pb.EntityProto representation of the model instance
       
   271   """
       
   272   return model_instance._populate_entity(_entity_class).ToPb()
       
   273 
       
   274 
       
   275 def model_from_protobuf(pb, _entity_class=datastore.Entity):
       
   276   """Decodes a model instance from a protocol buffer.
       
   277 
       
   278   Args:
       
   279     pb: The protocol buffer representation of the model instance. Can be an
       
   280         entity_pb.EntityProto or str encoding of an entity_bp.EntityProto
       
   281 
       
   282   Returns:
       
   283     Model instance resulting from decoding the protocol buffer
       
   284   """
       
   285   entity = _entity_class.FromPb(pb)
       
   286   return class_for_kind(entity.kind()).from_entity(entity)
       
   287 
       
   288 
   244 def _initialize_properties(model_class, name, bases, dct):
   289 def _initialize_properties(model_class, name, bases, dct):
   245   """Initialize Property attributes for Model-class.
   290   """Initialize Property attributes for Model-class.
   246 
   291 
   247   Args:
   292   Args:
   248     model_class: Model class to initialize properties for.
   293     model_class: Model class to initialize properties for.
   249   """
   294   """
   250   model_class._properties = {}
   295   model_class._properties = {}
       
   296   property_source = {}
       
   297 
       
   298   def get_attr_source(name, cls):
       
   299     for src_cls  in cls.mro():
       
   300       if name in src_cls.__dict__:
       
   301         return src_cls
       
   302 
   251   defined = set()
   303   defined = set()
   252   for base in bases:
   304   for base in bases:
   253     if hasattr(base, '_properties'):
   305     if hasattr(base, '_properties'):
   254       property_keys = base._properties.keys()
   306       property_keys = set(base._properties.keys())
   255       duplicate_properties = defined.intersection(property_keys)
   307       duplicate_property_keys = defined & property_keys
   256       if duplicate_properties:
   308       for dupe_prop_name in duplicate_property_keys:
   257         raise DuplicatePropertyError(
   309         old_source = property_source[dupe_prop_name] = get_attr_source(
   258             'Duplicate properties in base class %s already defined: %s' %
   310             dupe_prop_name, property_source[dupe_prop_name])
   259             (base.__name__, list(duplicate_properties)))
   311         new_source = get_attr_source(dupe_prop_name, base)
   260       defined.update(property_keys)
   312         if old_source != new_source:
   261       model_class._properties.update(base._properties)
   313           raise DuplicatePropertyError(
       
   314               'Duplicate property, %s, is inherited from both %s and %s.' %
       
   315               (dupe_prop_name, old_source.__name__, new_source.__name__))
       
   316       property_keys -= duplicate_property_keys
       
   317       if property_keys:
       
   318         defined |= property_keys
       
   319         property_source.update(dict.fromkeys(property_keys, base))
       
   320         model_class._properties.update(base._properties)
   262 
   321 
   263   for attr_name in dct.keys():
   322   for attr_name in dct.keys():
   264     attr = dct[attr_name]
   323     attr = dct[attr_name]
   265     if isinstance(attr, Property):
   324     if isinstance(attr, Property):
   266       check_reserved_word(attr_name)
   325       check_reserved_word(attr_name)
   555   __metaclass__ = PropertiedClass
   614   __metaclass__ = PropertiedClass
   556 
   615 
   557   def __init__(self,
   616   def __init__(self,
   558                parent=None,
   617                parent=None,
   559                key_name=None,
   618                key_name=None,
       
   619                key=None,
   560                _app=None,
   620                _app=None,
   561                _from_entity=False,
   621                _from_entity=False,
   562                **kwds):
   622                **kwds):
   563     """Creates a new instance of this model.
   623     """Creates a new instance of this model.
   564 
   624 
   580 
   640 
   581     Args:
   641     Args:
   582       parent: Parent instance for this instance or None, indicating a top-
   642       parent: Parent instance for this instance or None, indicating a top-
   583         level instance.
   643         level instance.
   584       key_name: Name for new model instance.
   644       key_name: Name for new model instance.
   585       _app: Intentionally undocumented.
   645       key: Key instance for this instance, overrides parent and key_name
   586       _from_entity: Intentionally undocumented.
   646       _from_entity: Intentionally undocumented.
   587       args: Keyword arguments mapping to properties of model.
   647       args: Keyword arguments mapping to properties of model.
   588     """
   648     """
   589     if key_name == '':
   649     if key is not None:
   590       raise BadKeyError('Name cannot be empty.')
   650       if isinstance(key, (tuple, list)):
   591     elif key_name is not None and not isinstance(key_name, basestring):
   651         key = Key.from_path(*key)
   592       raise BadKeyError('Name must be string type, not %s' %
   652       if isinstance(key, basestring):
   593                         key_name.__class__.__name__)
   653         key = Key(encoded=key)
   594 
   654       if not isinstance(key, Key):
   595     if parent is not None:
   655         raise TypeError('Expected Key type; received %s (is %s)' %
   596       if not isinstance(parent, (Model, Key)):
   656                         (key, key.__class__.__name__))
   597         raise TypeError('Expected Model type; received %s (is %s)' %
   657       if not key.has_id_or_name():
   598                         (parent, parent.__class__.__name__))
   658         raise BadKeyError('Key must have an id or name')
   599       if isinstance(parent, Model) and not parent.has_key():
   659       if key.kind() != self.kind():
   600         raise BadValueError(
   660         raise BadKeyError('Expected Key kind to be %s; received %s' %
   601             "%s instance must have a complete key before it can be used as a "
   661                           (self.kind(), key.kind()))
   602             "parent." % parent.kind())
   662       if _app is not None and key.app() != _app:
   603       if isinstance(parent, Key):
   663         raise BadKeyError('Expected Key app to be %s; received %s' %
   604         self._parent_key = parent
   664                           (_app, key.app()))
       
   665       if key_name is not None:
       
   666         raise BadArgumentError('Cannot use key and key_name at the same time')
       
   667       if parent is not None:
       
   668         raise BadArgumentError('Cannot use key and parent at the same time')
       
   669       self._key = key
       
   670       self._key_name = None
       
   671       self._parent = None
       
   672       self._parent_key = None
       
   673     else:
       
   674       if key_name == '':
       
   675         raise BadKeyError('Name cannot be empty.')
       
   676       elif key_name is not None and not isinstance(key_name, basestring):
       
   677         raise BadKeyError('Name must be string type, not %s' %
       
   678                           key_name.__class__.__name__)
       
   679 
       
   680       if parent is not None:
       
   681         if not isinstance(parent, (Model, Key)):
       
   682           raise TypeError('Expected Model type; received %s (is %s)' %
       
   683                           (parent, parent.__class__.__name__))
       
   684         if isinstance(parent, Model) and not parent.has_key():
       
   685           raise BadValueError(
       
   686               "%s instance must have a complete key before it can be used as a "
       
   687               "parent." % parent.kind())
       
   688         if isinstance(parent, Key):
       
   689           self._parent_key = parent
       
   690           self._parent = None
       
   691         else:
       
   692           self._parent_key = parent.key()
       
   693           self._parent = parent
       
   694       else:
       
   695         self._parent_key = None
   605         self._parent = None
   696         self._parent = None
   606       else:
   697       self._key_name = key_name
   607         self._parent_key = parent.key()
   698       self._key = None
   608         self._parent = parent
   699 
   609     else:
       
   610       self._parent_key = None
       
   611       self._parent = None
       
   612     self._entity = None
   700     self._entity = None
   613     self._key_name = key_name
       
   614     self._app = _app
   701     self._app = _app
   615 
   702 
   616     properties = self.properties()
       
   617     for prop in self.properties().values():
   703     for prop in self.properties().values():
   618       if prop.name in kwds:
   704       if prop.name in kwds:
   619         value = kwds[prop.name]
   705         value = kwds[prop.name]
   620       else:
   706       else:
   621         value = prop.default_value()
   707         value = prop.default_value()
   627 
   713 
   628   def key(self):
   714   def key(self):
   629     """Unique key for this entity.
   715     """Unique key for this entity.
   630 
   716 
   631     This property is only available if this entity is already stored in the
   717     This property is only available if this entity is already stored in the
   632     datastore, so it is available if this entity was fetched returned from a
   718     datastore or if it has a full key, so it is available if this entity was
   633     query, or after put() is called the first time for new entities.
   719     fetched returned from a query, or after put() is called the first time
       
   720     for new entities, or if a complete key was given when constructed.
   634 
   721 
   635     Returns:
   722     Returns:
   636       Datastore key of persisted entity.
   723       Datastore key of persisted entity.
   637 
   724 
   638     Raises:
   725     Raises:
   639       NotSavedError when entity is not persistent.
   726       NotSavedError when entity is not persistent.
   640     """
   727     """
   641     if self.is_saved():
   728     if self.is_saved():
   642       return self._entity.key()
   729       return self._entity.key()
       
   730     elif self._key:
       
   731       return self._key
   643     elif self._key_name:
   732     elif self._key_name:
   644       if self._parent_key:
       
   645         parent_key = self._parent_key
       
   646       elif self._parent:
       
   647           parent_key = self._parent.key()
       
   648       parent = self._parent_key or (self._parent and self._parent.key())
   733       parent = self._parent_key or (self._parent and self._parent.key())
   649       return Key.from_path(self.kind(), self._key_name, parent=parent)
   734       self._key = Key.from_path(self.kind(), self._key_name, parent=parent)
       
   735       return self._key
   650     else:
   736     else:
   651       raise NotSavedError()
   737       raise NotSavedError()
   652 
   738 
   653   def _to_entity(self, entity):
   739   def _to_entity(self, entity):
   654     """Copies information from this model to provided entity.
   740     """Copies information from this model to provided entity.
   673 
   759 
   674     Returns:
   760     Returns:
   675       Populated self._entity
   761       Populated self._entity
   676     """
   762     """
   677     self._entity = self._populate_entity(_entity_class=_entity_class)
   763     self._entity = self._populate_entity(_entity_class=_entity_class)
   678     if hasattr(self, '_key_name'):
   764     for attr in ('_key_name', '_key'):
   679       del self._key_name
   765       try:
       
   766         delattr(self, attr)
       
   767       except AttributeError:
       
   768         pass
   680     return self._entity
   769     return self._entity
   681 
   770 
   682   def put(self):
   771   def put(self):
   683     """Writes this model instance to the datastore.
   772     """Writes this model instance to the datastore.
   684 
   773 
   711     """
   800     """
   712     if self.is_saved():
   801     if self.is_saved():
   713       entity = self._entity
   802       entity = self._entity
   714     else:
   803     else:
   715       kwds = {'_app': self._app,
   804       kwds = {'_app': self._app,
   716               'name': self._key_name,
       
   717               'unindexed_properties': self._unindexed_properties}
   805               'unindexed_properties': self._unindexed_properties}
   718 
   806       if self._key is not None:
   719       if self._parent_key is not None:
   807         if self._key.id():
   720         kwds['parent'] = self._parent_key
   808           kwds['id'] = self._key.id()
   721       elif self._parent is not None:
   809         else:
   722         kwds['parent'] = self._parent._entity
   810           kwds['name'] = self._key.name()
       
   811         if self._key.parent():
       
   812           kwds['parent'] = self._key.parent()
       
   813       else:
       
   814         if self._key_name is not None:
       
   815           kwds['name'] = self._key_name
       
   816         if self._parent_key is not None:
       
   817           kwds['parent'] = self._parent_key
       
   818         elif self._parent is not None:
       
   819           kwds['parent'] = self._parent._entity
   723       entity = _entity_class(self.kind(), **kwds)
   820       entity = _entity_class(self.kind(), **kwds)
   724 
   821 
   725     self._to_entity(entity)
   822     self._to_entity(entity)
   726     return entity
   823     return entity
   727 
   824 
   747     return self._entity is not None
   844     return self._entity is not None
   748 
   845 
   749   def has_key(self):
   846   def has_key(self):
   750     """Determine if this model instance has a complete key.
   847     """Determine if this model instance has a complete key.
   751 
   848 
   752     Ids are not assigned until the data is saved to the Datastore, but
   849     When not using a fully self-assigned Key, ids are not assigned until the
   753     instances with a key name always have a full key.
   850     data is saved to the Datastore, but instances with a key name always have
   754 
   851     a full key.
   755     Returns:
   852 
   756       True if the object has been persisted to the datastore or has a key_name,
   853     Returns:
   757       otherwise False.
   854       True if the object has been persisted to the datastore or has a key
   758     """
   855       or has a key_name, otherwise False.
   759     return self.is_saved() or self._key_name
   856     """
       
   857     return self.is_saved() or self._key or self._key_name
   760 
   858 
   761   def dynamic_properties(self):
   859   def dynamic_properties(self):
   762     """Returns a list of all dynamic properties defined for instance."""
   860     """Returns a list of all dynamic properties defined for instance."""
   763     return []
   861     return []
   764 
   862 
   792       return self._parent_key
   890       return self._parent_key
   793     elif self._parent is not None:
   891     elif self._parent is not None:
   794       return self._parent.key()
   892       return self._parent.key()
   795     elif self._entity is not None:
   893     elif self._entity is not None:
   796       return self._entity.parent()
   894       return self._entity.parent()
       
   895     elif self._key is not None:
       
   896       return self._key.parent()
   797     else:
   897     else:
   798       return None
   898       return None
   799 
   899 
   800   def to_xml(self, _entity_class=datastore.Entity):
   900   def to_xml(self, _entity_class=datastore.Entity):
   801     """Generate an XML representation of this model instance.
   901     """Generate an XML representation of this model instance.
  1015       raise KindError('Class %s cannot handle kind \'%s\'' %
  1115       raise KindError('Class %s cannot handle kind \'%s\'' %
  1016                       (repr(cls), entity.kind()))
  1116                       (repr(cls), entity.kind()))
  1017 
  1117 
  1018     entity_values = cls._load_entity_values(entity)
  1118     entity_values = cls._load_entity_values(entity)
  1019     instance = cls(None, _from_entity=True, **entity_values)
  1119     instance = cls(None, _from_entity=True, **entity_values)
  1020     instance._entity = entity
  1120     if entity.is_saved():
  1021     del instance._key_name
  1121       instance._entity = entity
       
  1122       del instance._key_name
       
  1123       del instance._key
       
  1124     elif entity.key().has_id_or_name():
       
  1125       instance._key = entity.key()
  1022     return instance
  1126     return instance
  1023 
  1127 
  1024   @classmethod
  1128   @classmethod
  1025   def kind(cls):
  1129   def kind(cls):
  1026     """Returns the datastore kind we use for this model.
  1130     """Returns the datastore kind we use for this model.
  1124     else:
  1228     else:
  1125       key = model_or_key
  1229       key = model_or_key
  1126     keys.append(key)
  1230     keys.append(key)
  1127   datastore.Delete(keys)
  1231   datastore.Delete(keys)
  1128 
  1232 
       
  1233 def allocate_ids(model, size):
       
  1234   """Allocates a range of IDs of size for the model_key defined by model
       
  1235 
       
  1236   Allocates a range of IDs in the datastore such that those IDs will not
       
  1237   be automatically assigned to new entities. You can only allocate IDs
       
  1238   for model keys from your app. If there is an error, raises a subclass of
       
  1239   datastore_errors.Error.
       
  1240 
       
  1241   Args:
       
  1242     model: Model, Key or string to serve as a model specifying the ID sequence
       
  1243            in which to allocate IDs
       
  1244 
       
  1245   Returns:
       
  1246     (start, end) of the allocated range, inclusive.
       
  1247   """
       
  1248   models_or_keys, multiple = datastore.NormalizeAndTypeCheck(
       
  1249       model, (Model, Key, basestring))
       
  1250   keys = []
       
  1251   for model_or_key in models_or_keys:
       
  1252     if isinstance(model_or_key, Model):
       
  1253       key = model_or_key = model_or_key.key()
       
  1254     elif isinstance(model_or_key, basestring):
       
  1255       key = model_or_key = Key(model_or_key)
       
  1256     else:
       
  1257       key = model_or_key
       
  1258     keys.append(key)
       
  1259   return datastore.AllocateIds(keys, size)
  1129 
  1260 
  1130 class Expando(Model):
  1261 class Expando(Model):
  1131   """Dynamically expandable model.
  1262   """Dynamically expandable model.
  1132 
  1263 
  1133   An Expando does not require (but can still benefit from) the definition
  1264   An Expando does not require (but can still benefit from) the definition
  1320 
  1451 
  1321 
  1452 
  1322 class _BaseQuery(object):
  1453 class _BaseQuery(object):
  1323   """Base class for both Query and GqlQuery."""
  1454   """Base class for both Query and GqlQuery."""
  1324 
  1455 
  1325   def __init__(self, model_class, keys_only=False):
  1456   def __init__(self, model_class=None, keys_only=False):
  1326     """Constructor.
  1457     """Constructor.
  1327 
  1458 
  1328     Args:
  1459     Args:
  1329       model_class: Model class from which entities are constructed.
  1460       model_class: Model class from which entities are constructed.
  1330       keys_only: Whether the query should return full entities or only keys.
  1461       keys_only: Whether the query should return full entities or only keys.
  1426     raw = self._get_query().Get(limit, offset)
  1557     raw = self._get_query().Get(limit, offset)
  1427 
  1558 
  1428     if self._keys_only:
  1559     if self._keys_only:
  1429       return raw
  1560       return raw
  1430     else:
  1561     else:
  1431       return [self._model_class.from_entity(e) for e in raw]
  1562       if self._model_class is not None:
       
  1563         return [self._model_class.from_entity(e) for e in raw]
       
  1564       else:
       
  1565         return [class_for_kind(e.kind()).from_entity(e) for e in raw]
  1432 
  1566 
  1433   def __getitem__(self, arg):
  1567   def __getitem__(self, arg):
  1434     """Support for query[index] and query[start:stop].
  1568     """Support for query[index] and query[start:stop].
  1435 
  1569 
  1436     Beware: this ignores the LIMIT clause on GQL queries.
  1570     Beware: this ignores the LIMIT clause on GQL queries.
  1503       Next model instance.
  1637       Next model instance.
  1504 
  1638 
  1505     Raises:
  1639     Raises:
  1506       StopIteration when there are no more results in query.
  1640       StopIteration when there are no more results in query.
  1507     """
  1641     """
  1508     return self.__model_class.from_entity(self.__iterator.next())
  1642     if self.__model_class is not None:
       
  1643       return self.__model_class.from_entity(self.__iterator.next())
       
  1644     else:
       
  1645       entity = self.__iterator.next()
       
  1646       return class_for_kind(entity.kind()).from_entity(entity)
  1509 
  1647 
  1510 
  1648 
  1511 def _normalize_query_parameter(value):
  1649 def _normalize_query_parameter(value):
  1512   """Make any necessary type conversions to a query parameter.
  1650   """Make any necessary type conversions to a query parameter.
  1513 
  1651 
  1567 
  1705 
  1568      for story in Query(story).filter('title =', 'Foo').order('-date'):
  1706      for story in Query(story).filter('title =', 'Foo').order('-date'):
  1569        print story.title
  1707        print story.title
  1570   """
  1708   """
  1571 
  1709 
  1572   def __init__(self, model_class, keys_only=False):
  1710   def __init__(self, model_class=None, keys_only=False):
  1573     """Constructs a query over instances of the given Model.
  1711     """Constructs a query over instances of the given Model.
  1574 
  1712 
  1575     Args:
  1713     Args:
  1576       model_class: Model class to build query for.
  1714       model_class: Model class to build query for.
  1577       keys_only: Whether the query should return full entities or only keys.
  1715       keys_only: Whether the query should return full entities or only keys.
  1584   def _get_query(self,
  1722   def _get_query(self,
  1585                  _query_class=datastore.Query,
  1723                  _query_class=datastore.Query,
  1586                  _multi_query_class=datastore.MultiQuery):
  1724                  _multi_query_class=datastore.MultiQuery):
  1587     queries = []
  1725     queries = []
  1588     for query_set in self.__query_sets:
  1726     for query_set in self.__query_sets:
  1589       query = _query_class(self._model_class.kind(),
  1727       if self._model_class is not None:
       
  1728         kind = self._model_class.kind()
       
  1729       else:
       
  1730         kind = None
       
  1731       query = _query_class(kind,
  1590                            query_set,
  1732                            query_set,
  1591                            keys_only=self._keys_only)
  1733                            keys_only=self._keys_only)
  1592       query.Order(*self.__orderings)
  1734       query.Order(*self.__orderings)
  1593       if self.__ancestor is not None:
  1735       if self.__ancestor is not None:
  1594         query.Ancestor(self.__ancestor)
  1736         query.Ancestor(self.__ancestor)
  1663     if match.group(3) is not None:
  1805     if match.group(3) is not None:
  1664       operator = match.group(3)
  1806       operator = match.group(3)
  1665     else:
  1807     else:
  1666       operator = '=='
  1808       operator = '=='
  1667 
  1809 
  1668     if prop in self._model_class._unindexed_properties:
  1810     if self._model_class is None:
       
  1811       if prop != datastore_types._KEY_SPECIAL_PROPERTY:
       
  1812         raise BadQueryError(
       
  1813             'Only %s filters are allowed on kindless queries.' %
       
  1814             datastore_types._KEY_SPECIAL_PROPERTY)
       
  1815     elif prop in self._model_class._unindexed_properties:
  1669       raise PropertyError('Property \'%s\' is not indexed' % prop)
  1816       raise PropertyError('Property \'%s\' is not indexed' % prop)
  1670 
  1817 
  1671     if operator.lower() == 'in':
  1818     if operator.lower() == 'in':
  1672       if self._keys_only:
  1819       if self._keys_only:
  1673         raise BadQueryError('Keys only queries do not support IN filters.')
  1820         raise BadQueryError('Keys only queries do not support IN filters.')
  1709       property = property[1:]
  1856       property = property[1:]
  1710       order = datastore.Query.DESCENDING
  1857       order = datastore.Query.DESCENDING
  1711     else:
  1858     else:
  1712       order = datastore.Query.ASCENDING
  1859       order = datastore.Query.ASCENDING
  1713 
  1860 
  1714     if not issubclass(self._model_class, Expando):
  1861     if self._model_class is None:
  1715       if (property not in self._model_class.properties() and
  1862       if (property != datastore_types._KEY_SPECIAL_PROPERTY or
  1716           property not in datastore_types._SPECIAL_PROPERTIES):
  1863           order != datastore.Query.ASCENDING):
  1717         raise PropertyError('Invalid property name \'%s\'' % property)
  1864         raise BadQueryError(
  1718 
  1865             'Only %s ascending orders are supported on kindless queries' %
  1719     if property in self._model_class._unindexed_properties:
  1866             datastore_types._KEY_SPECIAL_PROPERTY)
  1720       raise PropertyError('Property \'%s\' is not indexed' % property)
  1867     else:
       
  1868       if not issubclass(self._model_class, Expando):
       
  1869         if (property not in self._model_class.properties() and
       
  1870             property not in datastore_types._SPECIAL_PROPERTIES):
       
  1871           raise PropertyError('Invalid property name \'%s\'' % property)
       
  1872 
       
  1873       if property in self._model_class._unindexed_properties:
       
  1874         raise PropertyError('Property \'%s\' is not indexed' % property)
  1721 
  1875 
  1722     self.__orderings.append((property, order))
  1876     self.__orderings.append((property, order))
  1723     return self
  1877     return self
  1724 
  1878 
  1725   def ancestor(self, ancestor):
  1879   def ancestor(self, ancestor):
  1772     """
  1926     """
  1773     from google.appengine.ext import gql
  1927     from google.appengine.ext import gql
  1774     app = kwds.pop('_app', None)
  1928     app = kwds.pop('_app', None)
  1775 
  1929 
  1776     self._proto_query = gql.GQL(query_string, _app=app)
  1930     self._proto_query = gql.GQL(query_string, _app=app)
  1777     model_class = class_for_kind(self._proto_query._entity)
  1931     if self._proto_query._entity is not None:
       
  1932       model_class = class_for_kind(self._proto_query._entity)
       
  1933     else:
       
  1934       model_class = None
  1778     super(GqlQuery, self).__init__(model_class,
  1935     super(GqlQuery, self).__init__(model_class,
  1779                                    keys_only=self._proto_query._keys_only)
  1936                                    keys_only=self._proto_query._keys_only)
  1780 
  1937 
  1781     for property, unused in (self._proto_query.filters().keys() +
  1938     if model_class is not None:
  1782                              self._proto_query.orderings()):
  1939       for property, unused in (self._proto_query.filters().keys() +
  1783       if property in model_class._unindexed_properties:
  1940                                self._proto_query.orderings()):
  1784         raise PropertyError('Property \'%s\' is not indexed' % property)
  1941         if property in model_class._unindexed_properties:
       
  1942           raise PropertyError('Property \'%s\' is not indexed' % property)
  1785 
  1943 
  1786     self.bind(*args, **kwds)
  1944     self.bind(*args, **kwds)
  1787 
  1945 
  1788   def bind(self, *args, **kwds):
  1946   def bind(self, *args, **kwds):
  1789     """Bind arguments (positional or keyword) to the query.
  1947     """Bind arguments (positional or keyword) to the query.
  2400     if self.auto_current_user:
  2558     if self.auto_current_user:
  2401       return users.get_current_user()
  2559       return users.get_current_user()
  2402     return super(UserProperty, self).get_value_for_datastore(model_instance)
  2560     return super(UserProperty, self).get_value_for_datastore(model_instance)
  2403 
  2561 
  2404   data_type = users.User
  2562   data_type = users.User
  2405 
       
  2406 
  2563 
  2407 
  2564 
  2408 class ListProperty(Property):
  2565 class ListProperty(Property):
  2409   """A property that stores a list of things.
  2566   """A property that stores a list of things.
  2410 
  2567