Compatibility of ndb models with WTForms - google-app-engine

Tech Stack: ndb models, WTForms, webapp2
I was experimenting with the WTForms extension to appengine db models.
I had a simple db schema:
class Autho(ndb.Models):
name = db.StringProperty()
class Notes(ndb.Model):
title = db.StringProperty()
author = db.KeyProperty()
and then a simple form definition form WTForms, in the handlers as per their documentation:
from wtforms.ext.appengine.db import model_form
def get(self, slug):
form = model_form(Author)()
self.render_template('form.html', {'form': form})
This raises an Attribute Error line 411 here props = model.properties()
Please let me know, if this can be fixed.

I've never used WTForms, but it seems to be incompatible with NDB -- "model.properties()" is an old db idiom. Maybe the WTForms author will consider adding support for NBD?

Check this out: https://github.com/coto/gae-boilerplate.
It's a ndb boilerplate with a basic (not so basic for me) implementation of user authentication that accepts federated login. It uses WTForms thoroughly. The guys that created it are very well reachable and the boilerplate is constantly maintained and updated. Worth a look, it helps a lot with basic patterns.

Related

Datastore entity access from ODK

I'm trying to access data that ODK has pushed into the datastore. The below code words fine when I query an entity that I created via Python, which was called "ProductSalesData". The entity name ODK has given it's data is "opendatakit.test1". When I update the data model to class opendatakit.test1(db.Model) it obviously bombs due to a sytax error. How do I call that data?
#!/usr/bin/env python
import webapp2
from google.appengine.ext import db
class ProductSalesData(db.Model):
product_id = db.IntegerProperty()
date = db.DateTimeProperty()
store = db.StringProperty()
q = ProductSalesData.all()
class simplequery(webapp2.RequestHandler):
def get(self):
for ProductSalesData in q:
self.response.out.write('Result:%s<br />' % ProductSalesData.store)
app = webapp2.WSGIApplication(
[('/', simplequery)],
debug=True)
I know you tagged GAE, but do you have to access it straight through the datastore?
If not, I've had better success using the API that has already been built into aggregate: https://code.google.com/p/opendatakit/wiki/BriefcaseAggregateAPI
If you need GAE access I'd suggest the ODK developers group over on google groups - they're pretty active.

EndpointsModel vs ndb.Model

So I stumbled on EndpointsModel as a means of creating models. When I look online, there is basically no tutorial about it. For people who have used it, what's the advantage? Instead of ndb.Model I mean.
Edit:
Also, I tried to mimic the code at What is the best way to auth, identify and store delicate information about users? just to check it out, but my eclipse red-lines it:
from endpoints_proto_datastore.ndb import EndpointsModel
The Endpoints Proto Datastore API is not an official part of the App Engine SDK, but a library I have been working on.
It is documented and I'm happy to come on here and answer your questions. As it turns out, EndpointsModel is a subclass of ndb.Model, so you are getting the best of both worlds:
>>> from endpoints_proto_datastore.ndb import EndpointsModel
>>> from google.appengine.ext import ndb
>>> EndpointsModel.__bases__ == (ndb.Model,)
True
As mentioned on the docs landing page, the advantage is that the library:
...allows existing model classes to be used with Google Cloud
Endpoints. By extending the functionality provided by ndb.Model class
and the endpoints library, this library allows you to directly
interact with model entities in your API methods rather than ProtoRPC
requests.
We have also given a talk on using the library. In it, we explicitly mention that you'll need to add the endpoints_proto_datastore library to your application.
$ cd path/to/your/application/code
$ wget https://endpoints-proto-datastore.googlecode.com/files/endpoints_proto_datastore.zip
$ unqip -q endpoints_proto_datastore.zip

What's a namespace used for in the App Engine datastore?

In the development admin console, when I look at my data, it says "Select different namespace".
What are namespaces for and how should I use them?
Namespaces allow you to implement segregation of data for multi-tenant applications. The official documentation links to some sample projects to give you an idea how it might be used.
Namespaces is used in google app engine to create Multitenant Applications. In Multitenent applications single instance of the application runs on a server, serving multiple client organizations (tenants). With this, an application can be designed to virtually partition its data and configuration (business logic), and each client organization works with a customized virtual application instance..you can easily partition data across tenants simply by specifying a unique namespace string for each tenant.
Other Uses of namespace:
Compartmentalizing user information
Separating admin data from application data
Creating separate datastore instances for testing and production
Running multiple apps on a single app engine instance
For More information visit the below links:
http://www.javacodegeeks.com/2011/12/multitenancy-in-google-appengine-gae.html
https://developers.google.com/appengine/docs/java/multitenancy/
http://java.dzone.com/articles/multitenancy-google-appengine
http://www.sitepoint.com/multitenancy-and-google-app-engine-gae-java/
Looking, towards this question is not that much good reviewed and answered so trying to give this one.
When using namespaces, we can have a best practice of key and value separation there on a given namespace. Following is the best example of giving the namespace information thoroughly.
from google.appengine.api import namespace_manager
from google.appengine.ext import db
from google.appengine.ext import webapp
class Counter(db.Model):
"""Model for containing a count."""
count = db.IntegerProperty()
def update_counter(name):
"""Increment the named counter by 1."""
def _update_counter(name):
counter = Counter.get_by_key_name(name)
if counter is None:
counter = Counter(key_name=name);
counter.count = 1
else:
counter.count = counter.count + 1
counter.put()
# Update counter in a transaction.
db.run_in_transaction(_update_counter, name)
class SomeRequest(webapp.RequestHandler):
"""Perform synchronous requests to update counter."""
def get(self):
update_counter('SomeRequest')
# try/finally pattern to temporarily set the namespace.
# Save the current namespace.
namespace = namespace_manager.get_namespace()
try:
namespace_manager.set_namespace('-global-')
update_counter('SomeRequest')
finally:
# Restore the saved namespace.
namespace_manager.set_namespace(namespace)
self.response.out.write('<html><body><p>Updated counters')
self.response.out.write('</p></body></html>')

GaeUtilities: Session Problem

I'm programming an application with google app engine, with django 1.1 (no django pacth or others), well as you know is impossible use django login and session features so I download
Gae utility and use Session Object (http://gaeutilities.appspot.com/) but some time this object create 2 sessions instead 1 session ... here's code
def index(request):
aSWrap = SWrap(SWrap.createSession())
....
def login(request):
aSWrap = SWrap(SWrap.createSession())
....
class SWrap(object):
#classmethod
def createSession():
return Session(cookie_name='my_cookie',session_expire_time=7200)
and for setting session no expiration or really long expiration...enter code here
Thanks
Judging by the code, you're calling createsession twice within the same request. That will cause problems with David's library as well.
Also, gaeutilties session included a config file where you can modify all the default values as you like.
https://github.com/joerussbowman/gaeutilities/blob/master/appengine_utilities/settings_default.py
gaeutilities session also has security features lacking in gae-sessions. I'm afraid David didn't attempt to answer you question, rather just suggested you use his library which under your current implementation would have the exact same problem. You need to be sure you only initiate the session once per http request no matter what session library you're using.
I'm moving gaeutilities session to a decorator in order to address this issue as well and provide better performance. You can watch the master branch on Github for updates. https://github.com/joerussbowman/gaeutilities
I suggest using a different sessions library. Check out this comparison of the available sessions libraries for GAE.
I'd recommend gae-sessions - it presents an API almost identical to the library you are currently using, but it is much faster and shouldn't give you headaches like the bug you've encountered above.
Disclaimer: I wrote gae-sessions, but I'm not the only one who would recommend it. Here is a recent thread discussing sessions on the google group for GAE python.
What are you trying to do with SWrap(SWrap.createSession())? It looks like the result of SWrap.createSession() is passed to the SWrap() constructor. Have you omitted part of the definition of SWrap?
Perhaps this is more what you are wanting:
def index(request):
mysession = SWrap.createSession()
....
def login(request):
mysession = SWrap.createSession()
....
class SWrap(object):
#staticmethod
def createSession():
return Session(cookie_name='my_cookie',session_expire_time=7200)

Bulkloading schema less entities on Google App Engine

The new bulkloader added into SDK 1.3.4 works great for models that
have a schema. For models inheriting db.Expando (or loosely defined
schemas) i would like to understand what i would have to do to bulk
upload them.
I defined a custom connector, that implemented the ConnectorInterface
and converted my data to the python dict required. How can i use this
dict to define entities that get uploaded to the data store ?
In the documentation there seems to be a post_import_function that can
be used to return the entities that get uploaded. Is there an example
on how this function is used ?
- kind: foo
connector: fooconnector
post_import_function: post_transform.post_import_fn
where,
def post_import_fn(input_dict, entity_instance, bulkload_state):
.....
is the function that is used for post_import. Hope this is useful for someone else.

Resources