This question completely follows on from a related question I had asked (and was answered) here: Error when trying to retrieve a single entity
As I understand, to retrieve a single entity from the datastore using a property other than helper methods already provided (e.g. 'id'
) requires turning a simple data property into an EndpointsAliasProperty
? If yes, how would I go about doing that? Or is it that we can only use 'id'
(helper methods provided by EndpointsModel
) and we cannot use any of the properties that we define (in this case 'title'
)?
The distinction between the custom
EndpointsAliasProperty
s and one of the data properties you defined is how they are used. They are all used to create aprotorpc
message, and that message is then converted into anEndpointsModel
with your custom data in it. THIS is where the magic happens.Breaking it down into steps:
1. You specify your data
2. You pick your fields for your method
3. A
protorpc
message class is defined from your fieldsThis happens every time a request is handled by a method decorated with
@MyModel.method
.4. A request comes in your application and a message is created
Using the
protorpc
message class, a message instance is parsed from the JSON which gets passed along to your Endpoints SPI (which is created byendpoints.api_server
).When the request comes in to your
protorpc.remote.Service
it is decoded:5. The
protorpc
message is cast into a datastore modelTHIS is the step you really care about. The
FromMessage
class method (also provided as part ofEndpointsModel
) loops through all the fieldsand for each field with a value set, turns the value into something to be added to the entity and separates based on whether the property is an
EndpointsAliasProperty
or not:After completing this loop, we have an ordered list
alias_args
of all key, value pairs and a dictionaryentity_kwargs
of the data attributes parsed from the message.Using these, first a simple entity is created
and then each of the alias property values are set in order:
The extended behavior happens in
setattr(entity, name, value)
. SinceEndpointsAliasProperty
is a subclass ofproperty
, it is a descriptor and it has asetter
which can perform some custom behavior beyond simply setting a value.For example, the
id
property is defined with:and the
setter
performs operations beyond simply setting data:This particular method attempts to retrieve the entity stored in the datastore using the
id
and patch in any values from the datastore that were not included in the entity parsed from the request.If you wanted to do this for a field like
my_attr
, you would need to construct a custom query which could retrieve the item with that uniquemy_attr
value (or fail if not exactly one such entity exists).This is problematic and you'd be better off using a unique field like the key or ID used to store the entity in the datastore.
The keys with ancestors sample gives a great example of creating your own custom properties.
If you REALLY insist on using
my_attr
to retrieve an entity, you could do so using a different property name (sincemy_attr
is already used for the data property) such asfromMyAttr
:Here, the
MyAttrSet
instance method would form the query:reject results that aren't unique for
my_attr
:and copy over the values for the already stored entity if we do find a unique one: