Problems with StructuredProperty and StringProperty - google-app-engine

i am doing the finally degree work in Google App Engine, but i am having problems when i try this:
class Predicate(ndb.Model):
name = ndb.StringProperty()
parameters = ndb.JsonProperty()
class State(ndb.Model):
predicates = ndb.StructuredProperty(Predicate, repeated=True)
class Action(ndb.Model):
name = ndb.StringProperty()
parameters = ndb.StringProperty(repeated=True)
preconditions = ndb.StructuredProperty(Predicate, repeated=True)
predicatesToAdd = ndb.StructuredProperty(Predicate, repeated=True)
predicatesToDel = ndb.StructuredProperty(Predicate, repeated=True)
class Plan(ndb.Model):
plan = ndb.StructuredProperty(Predicate, repeated=True)
class Problem(ndb.Model):
initialState = ndb.StructuredProperty(Predicate)
goalState = ndb.StructuredProperty(Predicate)
actions = ndb.StructuredProperty(Action, repeated=True)
i get this error:
TypeError: This StructuredProperty cannot use repeated=True because its model class (Predicate) contains repeated properties (directly or indirectly).
StructuredProperty, if it contains repetitions, can not be replicated another StructuredProperty. But I need this structure models. How can i solve this?
And sorry for my bad english :(
I solved this problem using LocalStructuredProperty, but I think it will not work at all

The problem with your design is that ndb does not allow nested repeated properties. In other words, you cannot have a repeated structured property, which in turn has its own repeated property. If you remove the repeated=True from the parameters property, it will work.
You will need to re-think your design to work around this. One possible solution may be to use a JsonProperty for parameters, and store the list of strings as a JSON string. You won't be able to query them then of course, but it may work out depending on your requirements.

Related

Datastore query two entity kinds, on a common property?

Say I have two entity kinds:
class image(db.Model):
url = db.LinkProperty()
date= db.DateTimeProperty()
class video(db.Model):
url = db.LinkProperty()
date= db.DateTimeProperty()
Which each may have some other (unimportant here) properties.
What I want to do is somehow merge the queries:
i = image.gql('ORDER BY date LIMIT 10')
v = video.gql('ORDER BY date LIMIT 10')
Such that I am left with a single GqlQuery object that is the result as if image and video were the same kind.
Is it possible without doing something like:
merged = ([a for a in i] + [b for b in v]).sort(key=lambda x: x.date)[:10]
Being left with an actual GqlQuery object instead of a list of entities would be a plus, though I have everything I need from the latter.
The only way with inheritance and different classes is to use a PolyModel then your class hierarchy would be
class Media(db.Model):
url = db.LinkProperty()
date= db.DateTimeProperty()
class Image(Media):
pass
class Video(Media):
pass
Then in GQL and preferably Query objects
To get all media types
query = Media.query().order(Media.date)
To just get Video
query = Video.query().order(Video.date)
Or don't have different classes. Have a single Media class and a field that denotes a media type.
Docs for PolyModel can be found here - https://developers.google.com/appengine/docs/python/ndb/polymodelclass

Google App Engine NDB repeated property additional info

For example: I have an Article model with a repeated "title" property that stores translations in different languages of the original title:
class Article(ndb.Model):
title = ndb.StringProperty(repeated=True)
How can I store, besides the title property, the language code of the title, so I can get specific versions of the title, something like this:
en_title = article.title['en']
It is important to have the same property name since I don't know in what language the article title will be queried by.
You can use repeated structure property:
class Title(ndb.Model):
title = ndb.StringProperty()
lang = ndb.StringProperty()
class Article(ndb.Model):
titles = ndb.StructuredProperty(Title, repeated=True)
Are you querying on the titles or languages? If not, you can use PickleProperty or JsonProperty to store a dict.

How to create JSON-Response when Entities are referenced via Ancestor?

Maybe my question is somehow unspecific, sorry for that. I'm learning python and app engine (webapp2) at the moment.
I have this class:
class Ice(db.Model):
"""Models an individual Guestbook entry with an author, content, and date."""
name = db.StringProperty()
description = db.StringProperty(multiline=True)
date = db.DateTimeProperty(auto_now_add=True)
def getTags(self):
return Tag.all().ancestor(self).fetch(10)
Tags are referenced via ancestor.
When I use a jinja-template i can call ice.getTags() foreach Ice.
Now i want to serialize my Ice-object to JSON and want to have all Tags that belong to the Ice-object in my JSON-Output.
This does serialisation for me:
It works okay, but it doesn't include the Tags.
I'm feeling, that i have to declare Tags as Ice-Attribute, but i don't know how.
class IceHandler(basehandler.BaseHandler):
def get(self):
ice_query = model.Ice.all().order('-date')
ices = ice_query.fetch(10)
self.response.write(json.encode(ices))
Thanks!

Storing GenericForeignKey content_type in another model?

I have a typical definition/instance situation in my data modeling. I'm trying to store the content_type of a GenericForeignKey in another model (the definition model) like so:
class IndicatorFieldInstance(models.Model):
definition = models.ForeignKey(IndicatorField)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey(definition.content_type, 'object_id')
indicator_instance = models.ForeignKey(IndicatorInstance)
I've also tried it like this:
content_object = generic.GenericForeignKey('definition__content_type', 'object_id')
Neither of these methods seem to work. Is it possible to achieve this?
For reference, here's the definition model:
class IndicatorField(models.Model):
name = models.CharField(max_length='255')
content_type = models.ForeignKey(ContentType)
indicator = models.ForeignKey(Indicator)
Thanks, Pete
If you don't mind doing the lookups yourself then you don't even need GenericForeignKey. Simply make it a property that does the lookup from the appropriate fields and returns the model. You'll lose any reverse functionality unless you do more work, but most of the time that isn't what is cared about.

Django models, custom functions

I am creating simple application with django. Also, I realized that I am doing some kind of operations very often. For example I often need to get all Article objects which have isPublick = True. So I am thinking is that possible to define get_published function in model?
if models looks like this (simplified)
class Article(models.Model):
title = models.CharField(...)
isPublished = models.BooleandField()
def get_active(self):
return Article.objects.filter(isPublicshed = 1)
But it doesn't work this way
Can you suggest a way of implementing the function?
What you probably want is a custom manager
From the django docs:
# An example of a custom manager called "objects".
class PersonManager(models.Manager):
def get_fun_people(self):
return self.filter(fun=True)
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
fun = models.BooleanField()
objects = PersonManager()
def __unicode__(self):
return u"%s %s" % (self.first_name, self.last_name)
which then allows you to do something like:
>>> p1 = Person(first_name='Bugs', last_name='Bunny', fun=True)
>>> p1.save()
>>> p2 = Person(first_name='Droopy', last_name='Dog', fun=False)
>>> p2.save()
>>> Person.objects.get_fun_people()
[<Person: Bugs Bunny>]
As is stated in the docs here, if you need to add custom row-level functionality to your objects, you need to define custom methods on your models. However, if what you are after is custom table-wide functionality (such as getting all Article objects that qualify certain conditions), you have to define custom methods on model Managers (much as aciniglio above points out in their answer).
You can use the staticmethod decorator.
class Article(models.Model):
title = models.CharField(...)
isPublished = models.BooleandField()
#staticmethod
def get_active():
return Article.objects.filter(isPublished = 1)

Resources