GAE - retrieving the last entry (python) - google-app-engine

I am trying to get the most recent data item from the datastore.
I am trying to apply the method as explained here but I am getting the object <__main__.Rep object at 0x075F1730> not the item. Can anyone explain what I am doing wrong?
The Model is:
class Rep(db.Model):
sent = db.StringProperty()
time = db.DateTimeProperty(auto_now_add=True)
This is the handler:
class Repeater(webapp.RequestHandler):
def get(self):
reps = Rep()
reps.sent = self.request.get('sentence')
reps.put()
s = self.request.get('sentence')
query = reps.all()
last = query.order('-time').get()
sentences = query
Thanks!

I don't see anything wrong at all.
<__main__.Rep object at 0x075F1730> is presumably an instance of your Rep class, as expected.

Related

NDB: How can I retrieve next/previous entity?

I'm writing an application for a factory where I need to provide a way for the user to retrieve the next (or previous) entity of a kind in NDB and can't figure out how to do this. Any help /tips will be appreciated!
Assume I have the following simplified model:
from google.appengine.ext import ndb
class Product(ndb.Model):
prod_id = ndb.StringProperty(required = True)
prod_desc = ndb.StringProperty(required = True)
prod_units = ndb.StringProperty(required = True)
... other properties
To allow the user to find a particular product I use the query below ('find' comes from a form filled in by the user).
Products_Str = 'Products' # The string ID for the common products ancestor
...
def get_products_key(products_key_str = Products_Str):
return ndb.Key('Products', Products_Str)
class DisplayProduct(BaseHandler): # Displays a product found on exact prod_id property
def post(self):
search_key = self.request.get('find')
find_query = Product.query(Product.prod_id == search_key, ancestor = get_products_key()).get()
... here I display the one result of the query, i.e. the requested product
So far so good: I provide the user with a way to find a specific product based on code (or description).
Now I need to place two buttons on the display page named "previous" and "next" and I can't figure out how to retrieve the next and previous products.
I would welcome any suggestions.

BadValueError: Expected string, got Key when creating child entity

Let me start by saying I'm really new to Python, app engine, and the datastore, so please be kind if I'm missing something obvious.
I'm trying to set up some data in the datastore with ancestor relationships, sort of the same way as in the example guestbook application from Google:
class Guestbook(webapp2.RequestHandler):
def post(self):
greeting = Greeting(parent=guestbook_key)
I created this code as an experiment to see if I could get it to work:
class Subscriber(ndb.Model):
user_nickname = ndb.StringProperty()
user_id = ndb.StringProperty()
class Music(ndb.Model):
level = ndb.StringProperty() # top or sub
parent = ndb.StringProperty() # only if sub
title = ndb.StringProperty()
class SetupHandler(webapp2.RequestHandler):
def get(self):
user = users.get_current_user()
subscriber = Subscriber(id=user.user_id())
subscriber.user_id = user.user_id()
subscriber.user_nickname = user.nickname()
haydn = Music(parent=subscriber.key)
haydn.level = "top"
haydn.title = "Haydn Trumpet Concerto"
haydn.put()
It seems to me as though I'm trying to do basically the same thing.. but I get this error:
File "... Application\datastoreexplore\main.py", line 41, in get
haydn = Music(parent=subscriber.key) BadValueError: Expected string, got Key('Subscriber', '12169615523634875051')
I've spent hours reading docs and searching through stackoverflow and elsewhere. I'm stumped. What am I doing wrong??
Your problem is thou have defined parent as a StringProperty but then passing in a key which is a valid constructor argument if you want to create an entity with anancestor. You should not have property called parent.

Updating existing entity in endpoints-proto-datastore

I am using Endpoints-proto-datastore written by Danny Hermes for Google App Engine and need help figuring out how to update an entity.. My model for what I need to update is the following
class Topic(EndpointsModel):
#_message_fields_schema = ('id','topic_name','topic_author')
topic_name = ndb.StringProperty(required=True)
topic_date = ndb.DateTimeProperty(auto_now_add=True)
topic_author = ndb.KeyProperty(required=True)
topic_num_views = ndb.IntegerProperty(default=0)
topic_num_replies = ndb.IntegerProperty(default=0)
topic_flagged = ndb.BooleanProperty(default=False)
topic_followers = ndb.KeyProperty(repeated=True)
topic_avg_rating = ndb.FloatProperty(default=0.0)
topic_total_rating = ndb.FloatProperty(default=0.0)
topic_num_ratings = ndb.IntegerProperty(default=0)
topic_raters = ndb.KeyProperty(repeated=True)
And as you can see, the rating properties have a default of 0. So each time a topic is rated, I need to update each of the rating properties. However, none of my properties is the actual rating being provided by the user. How can i pass in the value the user rated the topic to be able to update the properties in the model? Thanks!
You can do this by having an "alias" property called rating associated with your UserModel:
from endpoints_proto_datastore.ndb import EndpointsAliasProperty
class UserModel(EndpointsModel):
...
def rating_set(self, value):
# Do some validation
self._rating = value
#EndpointsAliasProperty(setter=rating_set)
def rating(self):
return self._rating
This will allow ratings to be sent with UserModels in requests but won't require those ratings to be stored.
You're better off using the OAuth 2.0 token for the user and calling endpoints.get_current_user() to determine who the user is in the request.
Something like a dedicated model for ratings could be much easier:
from endpoints_proto_datastore.ndb import EndpointsUserProperty
class Rating(EndpointsModel):
rater = EndpointsUserProperty(raise_unauthorized=True)
rating = ndb.IntegerProperty()
topic = ndb.KeyProperty(kind=Topic)
and then transactionally retrieving the Topic from the datastore and updating it in a request method decorated by #Rating.method.

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!

django i can't save form with 2 foreign keys

i have a Reply class:
class Reply(models.Model):
reply_to = models.ForeignKey(New)
creator = models.ForeignKey(User)
reply = models.CharField(max_length=140,blank=False)
a replay form:
class ReplyForm(ModelForm):
class Meta:
model = Reply
fields = ['reply']
where New is the Post class (containing users posts)
and a view
def save_reply(request):
#u = New.objects.get(pk=id)
if request.method == 'POST':
form = ReplyForm(request.POST)
if form.is_valid():
new_obj = form.save(commit=False)
new_obj.creator = request.user
new_obj.reply_to = form.reply_to
# reply_to_id = u
new_post = New(2) #this works hardcoded, but how can i get the blog New post #id, as a parameter, instead?
new_obj.reply_to = new_post
new_obj.save()
return HttpResponseRedirect('.')
else:
form = ReplyForm()
return render_to_response('replies/replies.html', {
'form': form,
},
context_instance=RequestContext(request))
where created_by belongs to New class and represents the creator of the post (which is to be replied)
how can i assign the current post to the reply under it?
thanks in advance!
I may have missed something, but reply_to needs an instance of the New model. New.id doesn't look like one to me?
new_obj.reply_to = New.id
Do you have an instance of the New model available at that point that you can assign?
ah, I see you've tweaked the question
If you don't have an instance of the New model, you'll need to create one
new_post = New(whatever, goes, here)
new_post.save()
Then assign it to reply_to
new_obj.reply_to = new_post
Or similar.
edit
Without knowing exactly that ReplyForm looks like I'm guessing a bit, but presumably it's based on the Reply object, letting the user select the reply_to field somehow or other?
Assuming that the form's reply_to variable is populated & correct I think you should just be able to do:
form = ReplyForm(request.POST)
if form.is_valid():
new_obj = form.save(commit=False)
new_obj.creator = request.user
new_obj.reply_to = form.reply_to
new_obj.save()
In fact since it's a foreign key, the new_obj = form.save(commit=False) may have already set .reply_to for you? The Django Model Forms docs may help.
Not sure if this'll be appropriate for your app or not, but you could try making use of a form widget, in particular the HiddenInput one to include the post (id) in the form. Something like
class ReplyForm(ModelForm):
reply_to = forms.ModelChoiceField(New.objects.all(), widget=forms.HiddenField)
class Meta:
model = Reply
fields = ['reply', 'reply_to']
widgets = {
'reply_to': HiddenField,
}
(Not sure that's entirely correct but see overriding-the-default-field-types-or-widgets for more).
You've now enabled the id you need to be passed to the client and back through the form, you now just need to put it in when you create the form for display in the first place
else:
form = ReplyForm()
form.reply_to = # ... fill in the current post (New inst) being replied to
# presumably from somewhere in the request object?
return render_to_response('replies/replies.html', { 'form': form, },
Hopefully that doesn't lead you off on the wrong track - completely untested, E&OE, YMMV, etc, etc

Resources