Multiple calls to put() method when updating ndb on google app engine - google-app-engine

I have a web app on GAE which uses a ndb database where each entity has as properties user informations and two string, the Entity class is like the one below
class UserPlus(ndb.Model):
user = ndb.UserProperty()
dogName = ndb.StringProperty(indexed=False)
catName = ndb.StringProperty(indexed=False)
The Main Page check if there's already an entity corresponding to that user, and if yes displays the value of the strings dogName and catName.
Then there's a form where users can update the values of dogName and catName . This performs a POST request to another page, the method below update the entiy
def post(self):
currentUser = users.get_current_user()
up = UserPlus.query(UserPlus.user==currentUser).get()
up.dogName = self.request.get('dog_name')
up.catName = self.request.get('cat_name')
weatherUser.put()
self.redirect('/')
But when I'm redirected to the Main Page, the values of dogName and catName are not updated until I refresh the page. I found that by calling the put() method two times instead of one, in the same position, this doesn't occur anymore, but I don't have clear why.
Am I doing something wrong or it's how ndb is supposed to work?

As Guido suspects and bossylobster/Fred Saur answered on my old question here - Should I expect stale results after redirect on local environment? - most likely eventual consistency problem.

Related

How I have to get data that store in database and uses in app of flask?

For example I have app on Flask with Postgresql. I have a some TOKENS and KEYS that stored in table companies. I need to get that tokens and keys in different places of my app. What the right way to do that? Any lazy approach?
Now I use app.config (but don't sure about app_context or before_first_request), for example:
with app.app_context():
if current_user:
app.config["CURRENT_COMPANY_ID"] = current_user.company_id
app.config["YANDEX_TOKEN"] =Company.query.filter_by(id=current_user.company_id).one().yandex_disk_token
or that:
with app.app_context():
if current_user:
g.company_id = current_user.company_id
g.yandex_token =Company.query.filter_by(id=current_user.company_id).one().yandex_disk_token
But that approaches sometimes lead to error that caused by current_user is None, or Company is None etc. And I can't recognize where and how I need store and get that TOKENS and KEY so all the users can use it after they are logged but not before that?
Find out:
It needs to update app.config constants before every user's request done. But if the current_user is not allowed (is None) then it will arise error so to make the current_user to not None we must use decorator #login_manager.request_loader
for example that code is placed in __init__ of app folder, and it solve two problems:
no empty current_user before every request we made to database via ORM.
no one request with empty app.config constants.
def set_config():
app.config['CURRENT_COMPANY_ID'] = current_user.company_id
app.config['YANDEX_TOKEN'] = Company.query.filter_by(id=current_user.company_id).first().yandex_disk_token
#login_manager.request_loader
def load_user_from_request(request):
user_id = request.headers.get('User-ID')
if user_id:
return UserModel.query.get(user_id)
return None
#app.before_request
def before_request():
if current_user.is_authenticated:
set_config()

webapp2 post operation not updating datastore

I am developing a web application using google appengine.
I am trying to update an existing entry in the table but my post operation does not seem to be working.
post script:
r = requests.post("http://localhost:8080", data={'type': 'user', 'id':
'11111', 'name': 'test'})
When running the script there are no errors in the console and when prining r.text I can see the updated name but the page on localhost does not show the updated name and the datastore user still has its previous name.
My model for the main page is:
class Page(webapp2.RequestHandler):
def get(self):
...
def post(self):
user = User().get_user(self.request.get('id')) // query user from data store
user.name = self.request.get('name')
user.put()
// update jinja template
self.request.get('id') is a string. You want to use an integer for the id, or build a key (I am assuming you are using ndb):
user = ndb.Key('User', int(self.request.get('id'))).get()

How to Refer a Parent table's key instead of the complete object instance in Django

I have just started working on Django, angularjs , The issue currently i am facing is I have created a model in django as following
**class Car_Booking(models.Model):
owner = models.ForeignKey('auth.User', related_name='booking_user')
car_id=models.IntegerField(max_length=4,default=1)
extra_field1=models.CharField(max_length=100,null=True)
extra_field2=models.CharField(max_length=50,null=True)
extra_field3=models.CharField(max_length=50,null=True)**
The Serializer is as following
**class CarBookingSerializer(serializers.HyperlinkedModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
class Meta:
model = Car_Booking
fields = ('car_id','owner','extra_field1','extra_field2','extra_field3')**
And view is as following
**class CarBookingViewSet(viewsets.ModelViewSet):
"""
This viewset automatically provides `list`, `create`, `retrieve`,
`update` and `destroy` actions.
Additionally we also provide an extra `highlight` action.
"""
queryset = Car_Booking.objects.all()
serializer_class = CarBookingSerializer
permission_classes = (permissions.AllowAny,
def perform_create(self, serializer):
serializer.save(owner=self.request.user)**
Now i developed a front end on Angularjs, the templelates i built were on the same server say localhost:8000 so when i call the view to insert the data by passing car_id, extra_field1, extra_field2 and extra_field 3 it gets saved successfully because i already get logged in and saved the user information into the cookies so i guess the Owner field is resolved automatically. Now when i call the same view from the IONIC framework on server localhost:5000(port is differnt) it give me the error, "Owner must be a user instance". I have searched a lot but can not find how to send the user authentication information, or save it accross the domains. Secondly i have tried to pass the owner_id but when i write the owner_id into the serializer it says "Owner_id is not a valid modlebase" but while calling throught the command prompt i can set the owner_id, Any Help on the following questions
***1. How can i send the username and password along the Post URL
How can i set the owner_id instead of OWNER object instance.***
Regards

Strange memcache behaviour on GAE

I'm doing a simple CRUD system with memcache to make reads of tables faster, but I'm a bit confused with the behaviour.
Basically, this is the important code:
class Book(db.Model):
title = db.StringProperty(required=True)
#classmethod
def getAll(cls):
key = 'booklist'
books = memcache.get(key)
if books is None:
logging.info('DB access for key %s.', key)
books = Book.all().order("title").fetch(100)
if not memcache.set(key, books, 300):
logging.error('Memcache set failed for key %s.', key)
else:
logging.info('Memcache for key %s.', key)
return books
# Save a Book and return it
#classmethod
def save(cls, title):
book = Book(title=title)
book.put()
# Flush memcache for this key
if memcache.delete('booklist') != 2:
logging.error('Memcache delete failed')
return book
In the app code I can add a book, so, once I get the title from the form, I do this:
book = Book.save(title)
if book is None:
logging.error('Book save error.')
self.redirect("/showBooks")
The last redirect gets me to this code:
def get(self):
books = Book.getAll()
self.renderPage("listBooks.htm", data=books)
Which only get all the books and display it on a table. The problem is that the steps are executed so quickly, or something like that, because the save function flushes the cache (it appears in the log), the getAll function writes in the log 'DB access for key booklist' but nothing appears in the table, like if GAE were still saving the data in the datastore and the new element have no time to be readed.
And, if you just wait 15 seconds and refresh the page, then the data is there.
I've tried other thing: instead of save and inmediately refresh the page with the redirection, I made an "intermediate info page" with the message "successfully saved". If I go to the listing page from this intermediate page, without touching any other code, all works fine (the new data appears in the table, like was expected). Again, this makes me to think that GAE needs time to save the object and my immediate read I was doing originally is faster.
Obviously, if I flush manually the memcache, in the next page refresh all the new data appears.
Can this be true? My read is faster than the GAE write and is this the problem I'm having?

(O)Auth with ExtJS

today i tried to get django-piston and ExtJS working. I used the ExtJS restful example and the piston example to create a little restful webapp. Everything works fine except the authentication.
Whats the best way to get Basic/Digest/OAuth authentication working with ExtJS?
Atm I'm not sure where to set the Username/Password.
Thanks
If you want to use piston with ExtJS, I would suggest writing an anonymous handler that checks the user is logged in via standard auth.
Try this:
class AnonymousUserProfileHandler(BaseHandler):
fields = ('title', 'url', 'affiliation')
model = UserProfile
def read(self, request, nickname):
profile = UserProfile.objects.get(nickname=nickname)
if request.user == profile.user:
return profile
class UserProfileHandler(BaseHandler):
anonymous = AnonymousUserProfileHandler
allowed_methods = ('GET')
fields = ('title', 'url', 'affiliation')
model = UserProfile
def read(self, request, nickname):
profile = UserProfile.objects.get(nickname=nickname)
return profile
In this example, when UserProfileHandler is called, without any authorization, it delegates to the anonymous handler. The anonymous handler checks whether the user is logged in via the usual request.user mode. If there is a valid user, it returns their profile object. You would then, obviously, mark the view calling this as requiring login.
The point is: when extJS makes its JSON call, it will send authentication data via the usual cookie. If you use an "anonymous" handler in Piston, but manually check the user is logged in before returning the data, then you essentially use traditional auth for your own site.

Resources