Как получить определенный объект, который является дочерним элементом родителя

Этот пост показывает мне как настроить родительско-дочерние отношения модели. Все работает нормально, за исключением того, что я не могу получить конкретную сущность, как в пример simple_get.

Я попытался украсить метод .method с помощью path='mymodel/{parent}/{id}', но model.from_datastore всегда имеет значение False.

Любое предложение о том, как правильно подключить это, приветствуется.

Спасибо.


person Rastio    schedule 28.10.2014    source источник


Ответы (1)


Хорошо, это была проблема курицы и яйца. Вот решение. Я создал базовый класс:

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

Используя этот пример, следует использоваться так:

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
person Rastio    schedule 28.10.2014