HOW to sort db.ReferenceProperty property? - google-app-engine

I have two kind like this:
class A(db.Model):
propertyA = db.XxxProperty(required=True)
class B(db.Model):
reference = db.ReferenceProperty(A,collection_name="Bs",required=True)
date = db.DateTimeProperty(auto_now_add=True)
Now I want make A.Bs has order, you konw, means using B.date to order A.Bs.
How can I do that? What GQL query should I write?
Thank you!

Try this
a.Bs.order("date")
or (for descending order):
a.Bs.order("-date")

Shay's suggestion is succinct and correct, though I think it would be helpful to add some more detail.
Using the same two class examples as in the question, I created the following class for rendering my page (GAE, python, jinja2)
class MainPage(Handler):
def get(self):
a_id = '1001' # magically get id of target entity a somehow
# get key using a_id, then retrieve entity using that
a = db.get(db.Key.from_path('A', a_id, parent=reg_key()))
# look up the collection and assign it to b
b = a.Bs
# sort items in collection in reverse
b.order('-created')
# pass b to the template to get rendered (I use a custom method in my Handler)
self.render('main.html', b = b)

Related

filter with dynamic dict peewee ORM

Using peewee as my ORM, is there a way to directly filter with a dict?
For example, if I have a model
class User(BaseModel):
username = CharField(unique=True)
password = CharField()
email = CharField()
join_date = DateTimeField()
How can I filter all results with username Bob, with something like
params = {'username':'Bob'}
User.select().where(**params)
update
I found a solution, but I'm wondering if there's a better way ...
params = {'username':'Bob'}
User.select().where(*[getattr(User, k) == v for k, v in params.items()])
First of all, where are you getting this "dynamic dict" from? Presumably you would want to do some field validation and things before just hucking shit at the database -- and during that time you could move it into a better data-structure.
Also note that the only operation you would be able to do with the above is equality testing.
To answer your question, Peewee has a .filter() method which behaves like the one in Django. So you can throw your dictionary of data at it. docs are sparse because this method is really not recommended:
http://docs.peewee-orm.com/en/latest/peewee/api.html#Model.filter

Modelling with ndb

I'm quite new to ndb. This is how my structure looks like in general:
a = [b, c]
b = [d, e, f]
d = [g, h]
e = [k, l, m, n]
f = [o]
c = [p, r, t]
I have the following model.
class Child(ndb.Model):
name = ndb.StringProperty()
child = ndb.KeyProperty(kind="Child", repeated=True)
class Root(ndb.Model):
name = ndb.StringProperty()
child = db.StructuredProperty(Child, repeated=True)
I can't do this since ndb won't allow me to repeat it because I already repeat Child.
What would be the proper way to model this structure?
Since the entities of the Root and Child kinds are almost the same, The data I see you are trying to model is a classic example of one-to-many relationship between entities of the same kind. The modelling for this sort of relationship is below:
class RelatedKind(ndb.Model):
name = ndb.StringProperty()
root = ndb.KeyProperty(kind="RelatedKind")
To create entities:
a = RelatedKind(name='a')
a_key = a.put()
b = RelatedKind(name='b', root=a_key)
b_key = b.put()
c = RelatedKind(name='c', root=a_key)
c_key = c.put()
# To get all 'child' of a;
child_a = RelatedKind.query(root == a_key).fetch()
print(child_a)
# >>> [b_key, c_key]
With datastore query, and just keyproperty, you achieve the same modelling without using repeated.
If you just want to be able to store many 'Child' entities on a single 'Root', you can use a LocalStructuredProperty to contain the Child model instead (but this means it won't be indexed). There's a hint to this behavior in the App Engine NDB docs when it discusses nested structured properties:
Although a StructuredProperty can be repeated and a StructuredProperty can contain another StructuredProperty, beware: if one structured property contains another, only one of them can be repeated. A work-around is to use LocalStructuredProperty, which does not have this constraint (but does not allow queries on its property values).
Another option for modeling nested relationships like this would be to use ancestors on the keys. So, for example, let's say your Root key path were: ('Root', 1). You could add children below it with keys ('Root', 1, 'Child', 1), ('Root', 1, 'Child', 5), and so on, appending 'Child' to the keypath each time. Then, we you wanted to query for the children of an object, you could just use an ancestor query, e.g.:
def create_child(parent, name):
new_child = Child(parent=parent.key, name=name)
new_child.put()
return new_child
def get_children(parent):
return Child.query(ancestor=parent.key)
class Child(ndb.Model):
name = ndb.StringProperty()
class Root(ndb.Model):
name = ndb.StringProperty()
You don't really even need to have a Root anymore at this point, because you can assign any arbitrary keypath, and you could also use the name as an ID instead and store less information.
That said, it's really completely dependent on what you're actually trying to model, there's not really enough information here to understand what you mean.
I don't see why you need a KeyProperty on the child. You could model your relationship like so:
class Child(ndb.Model):
name = ndb.StringProperty()
class Root(ndb.Model):
name = ndb.StringProperty()
child = ndb.KeyProperty(repeated=True)
c1 = Child(name="b").put()
c2 = Child(name="c").put()
a = Root(child=[c1,c2]).put() # put returns the key; otherwise you would need c1.key() here
children_keys = a.get().child # [Key(Child, 1234), Key(Child, 4567)]
# to retrieve the children, you could do
children = [ key.get() for key in children_keys ]
Keep in mind a few things. Suppose that you imagine records as being like files on your filesystem.
A KeyProperty is a pointer to another file.
A repeated property just stores multiple values.
There's no reason to use a structured property at all in this example, so let's skip that.
So, if you have the "root" object "contain" all the children via a repeated property, that'll result in you having a root file that can only be updated once every second or so, and it'll eventually grow too large.
So, in lieu of that, you have a few choices. You can use use ancestor queries, like Jeff mentioned. Or, you can just use all pointers and use a query to child any node's children:
class Node(ndb.Model):
parent = ndb.KeyProperty(kind='Node')
def get_children(self):
return Node.query().filter(Node.parent == self.key)
You can use get_children to fetch any node's children. Note that this part is eventually consistent, so recently added nodes won't necessarily show up in get_children for generally only a second or so.
root = Node(parent=None)
child1 = Node(parent=root)
child2 = Node(parent=root)
child3 = Node(parent=root)
sub_child1 = Node(parent=child1)

pattern for updating a datastore object

I'm wondering what the right pattern should be to update an existing datastore object using endpoints-proto-datastore.
For example, given a model like the one from your GDL videos:
class Task(EndpointsModel):
detail = ndb.StringProperty(required=True)
owner = ndb.StringProperty()
imagine we'd like to update the 'detail' of a Task.
I considered something like:
#Task.method(name='task.update',
path='task/{id}',
request_fields=('id', 'detail'))
def updateTask(self, task):
pass
However, 'task' would presumably contain the previously-stored version of the object, and I'm not clear on how to access the 'new' detail variable with which to update the object and re-store it.
Put another way, I'd like to write something like this:
def updateTask(self, task_in_datastore, task_from_request):
task_in_datastore.detail = task_from_request.detail
task_in_datastore.put()
Is there a pattern for in-place updates of objects with endpoints-proto-datastore?
Thanks!
See the documentation for details on this
The property id is one of five helper properties provided by default
to help you perform common operations like this (retrieving by ID). In
addition there is an entityKey property which provides a base64
encoded version of a datastore key and can be used in a similar
fashion as id...
This means that if you use the default id property your current object will be retrieved and then any updates from the request will replace those on the current object. Hence doing the most trivial:
#Task.method(name='task.update',
path='task/{id}',
request_fields=('id', 'detail'))
def updateTask(self, task):
task.put()
return task
will perform exactly what you intended.
Task is your model, you can easily update like this:
#Task.method(name='task.update',
path='task/{id}',
request_fields=('id', 'detail'))
def updateTask(self, task):
# Task.get_by_id(task.id)
Task.detail = task.detail
Task.put()
return task

Retrieving db.Property choices

Searching on the documentation provided by google and browsing SO I haven't found a way to retrieve the choices set on a db.Property object (I want to retrieve it in order to create forms based on the model).
I'm using the following recipe to do what I need, Is this correct? Is there any other way of doing it? (simpler, more elegant, more pythonic, etc.)
For a model like this:
class PhoneNumber(db.Model):
contact = db.ReferenceProperty(Contact,
collection_name='phone_numbers')
phone_type = db.StringProperty(choices=('home', 'work'))
number = db.PhoneNumberProperty()
I do the following modification:
class PhoneNumber(db.Model):
_phone_types = ('home', 'work')
contact = db.ReferenceProperty(Contact,
collection_name='phone_numbers')
phone_type = db.StringProperty(choices=_phone_types)
number = db.PhoneNumberProperty()
#classmethod
def get_phone_types(self):
return self._phone_types
You should be able to use PhoneNumber.phone_type.choices. If you want you could make that into a class method too:
#classmethod
def get_phone_types(class_):
return class_.phone_type.choices
You can decide if you prefer the class method approach or not.
Don't forget about Python's dir built-in! It is very useful when exploring objects.

Queries with JDOQL Unique Result Set

In my GAE application I want to make a JDOQL which returns a List where every element exist at most once even in the database there are more. How can I do this?
I dont know about JDOQL, but if you want a list where each entity exists utmost once i.e each list element is unique, then you could do the following:
Asume you have an entit type / model class that we call Type, with attributes att1,attr2.
You want to have a list of unique elements based on one or more of the attributes, say attr2.
you can use the following method that I adapted from a good source on the issue:
def unique(seq, idfun=None):
''' A function that returns a list of unique items in a very efficient manner
Refer to : http://www.peterbe.com/plog/uniqifiers-benchmark '''
# order preserving
if idfun is None:
def idfun(x): return x
seen = {}
result = []
for item in seq:
marker = idfun(item)
# in old Python versions:
# if seen.has_key(marker)
# but in new ones:
if marker in seen: continue
seen[marker] = 1
result.append(item)
return result
the to get a list of unique elements from the datastore type Type based on attr2 i could do something like:
list = Type.all()
unique_list = unique(list,lambda t: t.attr2)
Hope this helps because it has been the best method for me so far.

Resources