2014-10-28 6 views
0

This post은 부모 자식 모델 관계를 설정하는 방법을 보여줍니다. simple_get 예와 같이 특정 엔티티로 GET 할 수 없다는 점을 제외하고는 모두 정상적으로 작동합니다.부모의 자식 인 특정 엔터티를 검색하는 방법

.method를 path = 'mymodel/{parent}/{id}'로 꾸밀려고했지만 model.from_datastore는 항상 False입니다.

어떤 제안이든 제대로 연결하는 방법에 크게 감사드립니다.

감사합니다.

답변

0

좋아, 그건 닭고기와 달걀 문제였다. Here is the solution.

class BaseChildModel(EndpointsModel): 
    """ 
    Base child model class. 
    """ 

    # this needs to be set by inheritor 
    # this is a class of the NDB Entity parent, 
    # not an inheritance 
    parent_model_class = None 

    # These values are placeholders to be used when a key is created; the _parent 
    # will be used as the ancestor and the _id as the ID. For example: 
    # ndb.Key(parent_class, _parent, self.__class__, _id) 
    # Since these values will be set by alias properties which are not set 
    # simultaneously, we need to hold them around until both are present before we 
    # can create a key from them. 
    _parent = None 
    _id = None 

    # This is a helper method that will set the key on the entity only if both the 
    # parent and ID are present. It will be used by property setters that provide 
    # values for _parent and _id. 
    def set_key(self): 
     # if _parent ID is present, let's set the key 
     if self._parent is not None: 
      # we don't care if _id is None, the key like this will generate child ID 
      # for newly inserted child while keeping parent ID; i.e. this is insert 
      self._key = key = ndb.Key(self.__class__.parent_model_class, self._parent, self.__class__, self._id) 
      if self._id is not None: 
       # this is update/retrieve of existing child 
       # Will set the key and attempt to update the entity if it exists. 
       self.UpdateFromKey(key) 

    # This is a helper method that will set the _parent and _id values using the 
    # entity key, if it exists. It will be used by property getters that retrieve 
    # the current values of _parent and _id. 
    def set_parts(self): 
     # If there is no key, nothing can be set. 
     if self.key is not None: 
      # If there are not two tuples in the key pairs, a ValueError will occur. 
      parent_pair, id_pair = self.key.pairs() 
      # Each pair in key pairs will be a tuple (model kind, value) where model 
      # kind is a string representing the name of the model and value is the 
      # actual string or integer ID that was set. 
      self._parent = parent_pair[1] 
      self._id = id_pair[1] 

    # This is a setter which will be used by the alias property "parent". This 
    # method will be called when parent is set from a ProtoRPC request. 
    def parent_set(self, value): 
     self._parent = value 
     # After setting the value, we must make sure the parent exists before it can 
     # be used as an ancestor. 
     if ndb.Key(self.__class__.parent_model_class, value).get() is None: 
      # If the Parent key does not correspond to an entity in the datastore, 
      # we return an HTTP 404 Not Found. 
      raise endpoints.NotFoundException('Parent with id %s does not exist.' % value) 

     # The helper method SetKey is called to set the entity key if the _id has 
     # also been set already. 
     self.set_key() 

     # If the "parent" property is used in a query method, we want the ancestor 
     # of the query to be the parent key. 
     self._endpoints_query_info.ancestor = ndb.Key(self.__class__.parent_model_class, value) 

    # This EndpointsAliasProperty is used to get and set a parent for our entity 
    # key. It is required, meaning that a value must always be set if the 
    # corresponding field is contained in a ProtoRPC message schema. 
    @EndpointsAliasProperty(setter=parent_set, required=True, property_type=messages.IntegerField) 
    def parent(self): 
     # If _parent has not already been set on the entity, try to set it. 
     if self._parent is None: 
      # Using the helper method SetParts, _parent will be set if a valid key has 
      # been set on the entity. 
      self.set_parts() 

     return self._parent 

    # This is a setter which will be used by the alias property "id". This 
    # method will be called when id is set from a ProtoRPC request. This replaces 
    # the helper property "id" provided by EndpointsModel, but does not use any of 
    # the functionality from that method. 
    def IdSet(self, value): 
     self._id = value 
     # The helper method SetKey is called to set the entity key if the _parent 
     # has also been set already. 
     self.set_key() 

    # This EndpointsAliasProperty is used to get and set an id value for our 
    # entity key. It is required, meaning that a value must always be set if the 
    # corresponding field is contained in a ProtoRPC message schema. 
    @EndpointsAliasProperty(setter=IdSet, required=True, property_type=messages.IntegerField) 
    def id(self): 
     # If _id has not already been set on the entity, try to set it. 
     if self._id is None: 
      # Using the helper method SetParts, _id will be set if a valid key has 
      # been set on the entity. 
      self.set_parts() 
     return self._id 

그리고 this example를 사용하여, 그것과 같이 사용한다 :

class MyModel(BaseChildModel): 
    parent_model_class = MyParent 

    attr1 = ndb.StringProperty() 
    attr2 = ndb.StringProperty() 
    created = ndb.DateTimeProperty(auto_now_add=True) 

그 방법이 작동합니다

@MyModel.method(user_required=True, 
       http_method='PUT', 
       path='my_model/{parent}/{id}', 
       name='my_model.update') 
def MyModelUpdate(self, my_model): 
    if not my_model.from_datastore: 
     raise endpoints.NotFoundException('my_model not found.') 

    my_model.modified_by = endpoints.get_current_user() 
    my_model.put() 
    return my_model 
나는 기본 클래스를 만들었습니다
관련 문제