How to update data in google app engine - Python? - python

How do i update my records in google app engine?
I have my model with the following fields
doc_no = db.IntegerProperty()
title = db.StringProperty()
level = db.StringProperty()
What i want is to update the fields title and level, but i want to access the properties/attributes via a string like JavaScript objects i.e
if i do a select to the model
myRecord = db.GQLQuery('Select * from MyModelAbove where doc_no = 1')
Is it possible to access and update the properties like this;
myRecord['title']='New Tile'
myRecord['level']='Level2'
myRecord.put()
The one i have seen is this(not working for me);
myRecord.title = 'New Title'
NB: By the way google documentation is very scanty on this area

In your code sample, myRecords is a query. You must get the result before any modification:
result = myRecords.get()
Then, if you can't or don't want to access the title property with result.title, you could use setattr(result, 'title', 'New Title') then result.put()

Related

Django How to update model object fields from external api data

I have a script which runs on a scheduler to get data from an api which I then intend to use this data to update the current database model information.
My model ShowInfo within main/models.py:
from django.contrib.auth.models import User
class ShowInfo(models.Model):
title = models.CharField(max_length=50)
latest_ep_num = models.FloatField()
ld = models.BooleanField()
sd = models.BooleanField()
hd = models.BooleanField()
fhd = models.BooleanField()
following = models.ManyToManyField(User, related_name = 'following', blank=True)
I managed to isolate the issue to this section of the script which runs but inserts duplicate shows with the same titles into the database:
else: #test if api fails
for t in real_title:
if t in data_title: #testing if the titles in the database and from the api match
a = ShowInfo.objects.get(title=t)
id = a.id
b = next(item for item in show_list if item["title"] == t)
a1 = ShowInfo(id = id, title = b["title"], latest_ep_num=b["latest_ep_num"], ld=b["ld"], sd=b["sd"],hd=b["hd"],fhd=b["fhd"])
a1.save()
Some additional info about the lists (where show_list is a list of dictionaries gotten from an api):
database = ShowInfo.objects.values()
real_title = []
data_title = []
for show in show_list:
real_title.append(show["title"])
for data in database:
data_title.append(data["title"])
When the script runs I notice from browsing my database with DB Browser for SQLite that the objects were being inserted and not updating as i intended.
The script is supposed to catch shows with the same title from the api and the database and to update any changed information. Does anyone have any idea what is wrong with my save() method?
After a day of trial and error and scrounging around the internet I finally found a solution that worked for me.
For anyone interested, this is the solution that I found from another user on Stack which utilized overriding the internal save method to force an update and not insert if the current object with the same field is already in the DB.
Other methods such as doing force_update=True or update_or_create() did not work in my case.

GAE Python Query ordering won't take certain properties

In the official tutorial for GAE guestbook, I'm trying to change the order of query results like so:
greetings_query = Greeting.query(
ancestor=guestbook_key(guestbook_name)).order(Greeting.content)
Greeting looks like this:
class Greeting(ndb.Model):
content = ndb.StringProperty(indexed=False)
date = ndb.DateTimeProperty(auto_now_add=True)
Passing Greeting.date obviously works.
What could be the reason?

How to save an embedded object in GAE?

I'm trying to save a datastore entity reference within another:
class Save(webapp2.RequestHandler):
def get(self):
order = Order(parent=ndb.Key('Orders', 'default_orders'))
order.special_request = self.request.get('specialRequirement')
order.product_type = self.request.get('productType')
customer = Customer(parent=ndb.Key('Customer', 'default_customers'))
customer.name = self.request.get('customerName')
customer.email = self.request.get('email')
customer.put()
order.customer = customer
order.put()
The Customer class is simply:
from google.appengine.ext import ndb
class Customer(ndb.Model):
name = ndb.StringProperty()
email = ndb.StringProperty()
Whilst I've done similar with Rails and mongodb before, I'm not sure what this is called in GAE and am having a hard time searching for examples.
Ok, the following seems to have been my oversight, simply passing the key as:
oder.customer = customer.key
I now have a usable reference to the embedded object and both are being saved correctly.

Google App Engine return object with reference set

Hi I am kind of trying to get the concept behind DataStore as a No-SQL database, what I am trying to fetch is a list of object wich have been "reference" by another. As this
class Person(db.Model):
name = db.StringProperty(required=True)
class Contact(db.Model):
name = db.StringProperty(required=True)
email = db.StringProperty()
trader = db.ReferenceProperty(Person)
This works fine and they get to be saved when I use person.put() without any problem. But when I try to retrieve it and encoded as json it nevers shows me the contact as a list in fact it totally ignores it.
persons_query = Person.all()
persons = persons_query.fetch(50)
data = json.encode(persons)
I would expect person to have a collection of Contact but it doesn't any ideas on how to solve this problem?
To make it clearer currently i am getting something like this:
[
{
name: "John Doe"
}
]
I would like to be
[
{
name: "John Doe"
contacts: [{name:"Alex", email:'alex#gmail.com'}]
}
]
Edit
Thanks all you were right I needed to fetch the collection of contacts there was only one issue for this is that when Contact was being encoded it recursively tried to encode the Trader object and this it's contact and so on.
So I got an obvious error recursive error, the solution to this was clearly to remove the trader object from the Contact when it's being encoded.
Make a custom toJson function in your class
class Person(db.Model):
name = db.StringProperty(required=True)
def toJson(self):
contact = self.contact_set #this is the default collection name for your class
d = {"name":self.name,"contact":contact}
return json.dumps(d)
class Contact(db.Model):
name = db.StringProperty(required=True)
email = db.StringProperty()
trader = db.ReferenceProperty(Person)
then you may do the ff:
persons_query = Person.all()
persons = persons_query.fetch(50)
data = person.toJson()
To fetch all the contacts you will need to write a custom json encoder, which fetches all of the reverse of the reference property.
ReferenceProperties automatically get a reverse query. From the docs "collection_name is the name of the property to give to the referenced model class. The value of the property is a Query for all entities that reference the entity. If no collection_name is set, then modelname_set (with the name of the referenced model in lowercase letters and _set added) is used."
So you would add a method to resolve the reverse reference set query.
class Person(db.Model):
name = db.StringProperty(required=True)
def contacts(self):
return self.contact_set.fetch(50) # should be smarter than that
Then use it in your custom json encoder.
If you want to find all the contacts that include a person you will need to issue a query for it.
contacts = Contact.all().filter("trader =", person)

How to query datastore when using ReferenceProperty?

I am trying to understand the 1-to-many relationships in datastore; but I fail to understand how query and update the record of a user when the model includes ReferenceProperty. Say I have this model:
class User(db.Model):
userEmail = db.StringProperty()
userScore = db.IntegerProperty(default=0)
class Comment(db.Model):
user = db.ReferenceProperty(User, collection_name="comments")
comment = db.StringProperty()
class Venue(db.Model):
user = db.ReferenceProperty(User, collection_name="venues")
venue = db.StringProperty()
If I understand correctly, the same user, uniquely identified by userEmail can have many comments and may be associated with many venues (restaurants etc.)
Now, let's say the user az#example.com is already in the database and he submits a new entry.
Based on this answer I do something like:
q = User.all()
q.filter("userEmail =", az#example.com)
results = q.fetch(1)
newEntry = results[0]
But I am not clear what this does! What I want to do is to update comment and venue fields which are under class Comment and class Venue.
Can you help me understand how this works? Thanks.
The snippet you posted is doing this (see comments):
q = User.all() # prepare User table for querying
q.filter("userEmail =", "az#example.com") # apply filter, email lookup
- this is a simple where clause
results = q.fetch(1) # execute the query, apply limit 1
the_user = results[0] # the results is a list of objects, grab the first one
After this code the_user will be an object that corresponds to the user record with email "az#example.com". Seing you've set up your reference properties, you can access its comments and venues with the_user.comments and the_user.venues. Some venue of these can be modified, say like this:
some_venue = the_user.venues[0] # the first from the list
some_venue.venue = 'At DC. square'
db.put(some_venue) # the entry will be updated
I suggest that you make a general sweep of the gae documentation that has very good examples, you will find it very helpful:
http://code.google.com/appengine/docs/python/overview.html
** UPDATE **: For adding new venue to user, simply create new venue and assign the queried user object as the venue's user attribute:
new_venue = Venue(venue='Jeferson memorial', user=the_user) # careful with the quoting
db.put(new_venue)
To get all Comments for a given user, filter the user property using the key of the user:
comments = Comment.all().filter("user =", user.key()).fetch(50)
So you could first lookup the user by the email, and then search comments or venues using its key.

Categories

Resources