I have used the getting started guide of app engine.But I am unable to use the datastore.
While running the simple code provided in the guide, i am getting "cannot access apps data" error.
my code :
import cgi
import datetime
import urllib
import webapp2
from google.appengine.ext import db
from google.appengine.api import users
MAIN_PAGE_FOOTER_TEMPLATE = """\
<form action="/sign?%s" method="post">
<div><textarea name="content" rows="3" cols="60"></textarea></div>
<div><input type="submit" value="Sign Guestbook"></div>
</form>
<hr>
<form>Guestbook name: <input value="%s" name="guestbook_name">
<input type="submit" value="switch"></form>
</body>
</html>
"""
class Greeting(db.Model):
"""Models an individual Guestbook entry with author, content, and date."""
author = db.StringProperty()
content = db.StringProperty(multiline=True)
date = db.DateTimeProperty(auto_now_add=True)
def guestbook_key(guestbook_name=None):
"""Constructs a Datastore key for a Guestbook entity with guestbook_name."""
return db.Key.from_path('Guestbook', guestbook_name or 'default_guestbook')
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.write('<html><body>')
guestbook_name = self.request.get('guestbook_name')
# Ancestor Queries, as shown here, are strongly consistent with the High
# Replication Datastore. Queries that span entity groups are eventually
# consistent. If we omitted the ancestor from this query there would be
# a slight chance that Greeting that had just been written would not
# show up in a query.
greetings = db.GqlQuery("SELECT * "
"FROM Greeting "
"WHERE ANCESTOR IS :1 "
"ORDER BY date DESC LIMIT 10",
guestbook_key(guestbook_name))
for greeting in greetings:
if greeting.author:
self.response.write(
'<b>%s</b> wrote:' % greeting.author)
else:
self.response.write('An anonymous person wrote:')
self.response.write('<blockquote>%s</blockquote>' %
cgi.escape(greeting.content))
# Write the submission form and the footer of the page
sign_query_params = urllib.urlencode({'guestbook_name': guestbook_name})
self.response.write(MAIN_PAGE_FOOTER_TEMPLATE %
(sign_query_params, cgi.escape(guestbook_name)))
class Guestbook(webapp2.RequestHandler):
def post(self):
# We set the same parent key on the 'Greeting' to ensure each greeting
# is in the same entity group. Queries across the single entity group
# will be consistent. However, the write rate to a single entity group
# should be limited to ~1/second.
guestbook_name = self.request.get('guestbook_name')
greeting = Greeting(parent=guestbook_key(guestbook_name))
if users.get_current_user():
greeting.author = users.get_current_user().nickname()
greeting.content = self.request.get('content')
greeting.put()
query_params = {'guestbook_name': guestbook_name}
self.redirect('/?' + urllib.urlencode(query_params))
app = webapp2.WSGIApplication([('/', MainPage),
('/sign', Guestbook)],
debug=True)
I have uploaded the app on the server, but still getting the same error.
Traceback (most recent call last):
File "/home/laxman/google_appengine/lib/webapp2/webapp2.py", line 1535, in __call__
rv = self.handle_exception(request, response, e)
File "/home/laxman/google_appengine/lib/webapp2/webapp2.py", line 1529, in __call__
rv = self.router.dispatch(request, response)
File "/home/laxman/google_appengine/lib/webapp2/webapp2.py", line 1278, in default_dispatcher
return route.handler_adapter(request, response)
File "/home/laxman/google_appengine/lib/webapp2/webapp2.py", line 1102, in __call__
return handler.dispatch()
File "/home/laxman/google_appengine/lib/webapp2/webapp2.py", line 572, in dispatch
return self.handle_exception(e, self.app.debug)
File "/home/laxman/google_appengine/lib/webapp2/webapp2.py", line 570, in dispatch
return method(*args, **kwargs)
File "/home/laxman/helloworld/helloworld.py", line 51, in get
for greeting in greetings:
File "/home/laxman/google_appengine/google/appengine/ext/db/__init__.py", line 2326, in next
return self.__model_class.from_entity(self.__iterator.next())
File "/home/laxman/google_appengine/google/appengine/datastore/datastore_query.py", line 2892, in next
next_batch = self.__batcher.next()
File "/home/laxman/google_appengine/google/appengine/datastore/datastore_query.py", line 2754, in next
return self.next_batch(self.AT_LEAST_ONE)
File "/home/laxman/google_appengine/google/appengine/datastore/datastore_query.py", line 2791, in next_batch
batch = self.__next_batch.get_result()
File "/home/laxman/google_appengine/google/appengine/api/apiproxy_stub_map.py", line 604, in get_result
return self.__get_result_hook(self)
File "/home/laxman/google_appengine/google/appengine/datastore/datastore_query.py", line 2528, in __query_result_hook
self._batch_shared.conn.check_rpc_success(rpc)
File "/home/laxman/google_appengine/google/appengine/datastore/datastore_rpc.py", line 1224, in check_rpc_success
raise _ToDatastoreError(err)
BadRequestError: app "dev~helloworld" cannot access app "dev~hellolxmn"'s data
For the dev server the answer is in your the last line of your stacktrace.
app "dev~helloworld" cannot access app "dev~hellolxmn"'s data
You probably have an app.yaml which has changed it's appid, over time and you haven't
created a new datastore. You should show us you current app.yaml.
My guess is your error will be a little different in product, so show the trace for the error in production.
I copied and pasted your code and it seems to be working (I had to change formatting)
What is in your app.yaml? (I named my file aaa.py) this is what i used
application: somename
version: 1
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /.*
script: aaa.app
Related
I cleared all entities from the datastore and cleared the memcache, created an entity using the API Explorer and then attempted to create another one of the same kind in the Datastore console running on localhost:
Internal Server Error
The server has either erred or is incapable of performing the requested operation.
Traceback (most recent call last):
File "/home/tom/work/google-cloud-sdk/platform/google_appengine/lib/webapp2-2.5.1/webapp2.py", line 1536, in __call__
rv = self.handle_exception(request, response, e)
File "/home/tom/work/google-cloud-sdk/platform/google_appengine/lib/webapp2-2.5.1/webapp2.py", line 1530, in __call__
rv = self.router.dispatch(request, response)
File "/home/tom/work/google-cloud-sdk/platform/google_appengine/lib/webapp2-2.5.1/webapp2.py", line 1278, in default_dispatcher
return route.handler_adapter(request, response)
File "/home/tom/work/google-cloud-sdk/platform/google_appengine/lib/webapp2-2.5.1/webapp2.py", line 1102, in __call__
return handler.dispatch()
File "/home/tom/work/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/admin/admin_request_handler.py", line 97, in dispatch
super(AdminRequestHandler, self).dispatch()
File "/home/tom/work/google-cloud-sdk/platform/google_appengine/lib/webapp2-2.5.1/webapp2.py", line 572, in dispatch
return self.handle_exception(e, self.app.debug)
File "/home/tom/work/google-cloud-sdk/platform/google_appengine/lib/webapp2-2.5.1/webapp2.py", line 570, in dispatch
return method(*args, **kwargs)
File "/home/tom/work/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/admin/datastore_viewer.py", line 760, in get
count=20)
File "/home/tom/work/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/admin/datastore_viewer.py", line 121, in _get_entities
query = datastore.Query(kind, _namespace=namespace)
File "/home/tom/work/google-cloud-sdk/platform/google_appengine/google/appengine/api/datastore.py", line 1361, in __init__
datastore_errors.BadArgumentError)
File "/home/tom/work/google-cloud-sdk/platform/google_appengine/google/appengine/api/datastore_types.py", line 181, in ValidateString
raise exception('%s must not be empty.' % name)
BadArgumentError: kind must not be empty.
Here's the gcloud version info:
$ gcloud --version
Google Cloud SDK 157.0.0
app-engine-python 1.9.54
beta 2017.03.24
bq 2.0.24
core 2017.05.30
gcloud
gsutil 4.26
Any hints as to what might be wrong?
I think it's a bug in the Datastore console.
I was able to replicate the same error on my machine. If you look at the traceback in the exception, you see (fourth from the bottom):
File "/.../google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/admin/datastore_viewer.py", line 760, in get
count=20)
If you look at that file from line 735, you see:
def get(self, entity_key_string=None):
super(DatastoreEditRequestHandler, self).get(entity_key_string)
if entity_key_string:
entity_key = datastore.Key(entity_key_string)
entity_key_name = entity_key.name()
entity_key_id = entity_key.id()
namespace = entity_key.namespace()
kind = entity_key.kind()
entities = [datastore.Get(entity_key)]
parent_key = entity_key.parent()
if parent_key:
parent_key_string = _format_datastore_key(parent_key)
else:
parent_key_string = None
else:
entity_key = None
entity_key_string = None
entity_key_name = None
entity_key_id = None
namespace = self.request.get('namespace')
kind = self.request.get('kind')
entities, _ = _get_entities(kind,
namespace,
order=None,
start=0,
count=20) ### line 760 #######
...
In that last line, kind is supposed to be string containing the model name of the model you are working with. Instead, if you follow the traceback down into that function call, you see that kind is an empty string. I don't think there's much you can do to fix it at this time. I'd recommend using the interactive console for now to create/edit your Datastore entities, and just use the viewer to view them. I'm sure Google will fix this with an update soon.
Edit: I actually found a hacky fix if you really want the Datastore console to work, but I would still recommend just using the interactive console. The hacky fix is you manually enter the kind variable into the URL sent by the Datastore console.
When you click "Create New Entity" and get the error you show in your question, look at the url:
http://localhost:8000/datastore/edit?kind=&next=http%3A%2F%2Flocalhost%3A8000%2Fdatastore%3Fkind%3DUnique
You see ...:8000/datastore/edit?kind=&.... Right there, just type in the model name. For example, let's say your model name is User:
http://localhost:8000/datastore/edit?kind=User&next=http%3A%2F%2Flocalhost%3A8000%2Fdatastore%3Fkind%3DUnique
This brought me to the "Create new entity" form for class User (one of my models), and I was able to create a user with that form.
P.S. You may want to also change the model name on the very end of that url (where mine says Unique) to match the kind you are creating, because that model name is the kind that will be displayed after you create your new entity. So mine created a User, but then displayed the Unique entities (Unique is one of my model names).
Use the example code from app engine will give an attribute error. The more strange thing is,
When the batch_size is 100, the first fetch will give an error while if it were set to 10, the second fetch will give the error, when the batch_size is 1, the 25th fetch will give the error. Is it due to the problem of remote API?
Python version: 2.7
App engine sdk version: 1.9.6
query = MyModel.all()
entities = query.fetch(100)
while entities:
for entity in entities:
# Do something with entity
query.with_cursor(query.cursor())
entities = query.fetch(100)
error message:
Traceback (most recent call last):
File "migrate.py", line 77, in <module>
entities = query.fetch(batch_size)
File "/home/kamel/Library/google_appengine/google/appengine/ext/db/__init__.py", line 2157, in fetch
return list(self.run(limit=limit, offset=offset, **kwargs))
File "/home/kamel/Library/google_appengine/google/appengine/ext/db/__init__.py", line 2326, in next
return self.__model_class.from_entity(self.__iterator.next())
File "/home/kamel/Library/google_appengine/google/appengine/ext/db/__init__.py", line 1435, in from_entity
entity_values = cls._load_entity_values(entity)
File "/home/kamel/Library/google_appengine/google/appengine/ext/db/__init__.py", line 1413, in _load_entity_values
value = prop.make_value_from_datastore(value)
File "/home/kamel/labola/src/model/properties.py", line 295, in make_value_from_datastore
return pickle.loads(value)
File "/usr/lib/python2.7/pickle.py", line 1382, in loads
return Unpickler(file).load()
File "/usr/lib/python2.7/pickle.py", line 858, in load
dispatch[key](self)
File "/usr/lib/python2.7/pickle.py", line 1083, in load_newobj
obj = cls.__new__(cls, *args)
AttributeError: class Reference has no attribute '__new__
I encountered the same issue when trying to unpickle python3 pickles under python2. The problem was linked to new-style classes becoming default in python3. (source)
Solution for me was to replace class AClass: by class AClass(object):
I read the "what is a metaclass in Python" but am still confused over it.
I am new to python and have been thrown into upgrading it from 2.5 to 2.7.
I have the following:
class UsersDB(db.Model):
Email = db.EmailProperty(required=True,verbose_name='Email *')
Enable = db.BooleanProperty(default=True)
and
class UsersQuickAddForm(forms.ModelForm):
def is_user_exist(self, account):
users_query = UsersDB.all().filter('Email =', account).fetch(1)
if len(users_query) > 0:
return True
return False
class Meta:
model = UsersDB
exclude = ['Enable']
but when I try to execute it on the google site, I get:
Traceback (most recent call last):
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/runtime/wsgi.py", line 239, in Handle
handler = _config_handle.add_wsgi_middleware(self._LoadHandler())
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/runtime/wsgi.py", line 298, in _LoadHandler
handler, path, err = LoadObject(self._handler)
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/runtime/wsgi.py", line 84, in LoadObject
obj = import(path[0])
File "/base/data/home/apps/s~ldsdgidev/glen27.371429613087607751/LDSGH.py", line 8, in
from core.decorators import permissionRequired
File "/base/data/home/apps/s~ldsdgidev/glen27.371429613087607751/core/decorators.py", line 7, in
from core.initialization import loginIf
File "/base/data/home/apps/s~ldsdgidev/glen27.371429613087607751/core/initialization.py", line 6, in
import photo_images
File "/base/data/home/apps/s~ldsdgidev/glen27.371429613087607751/core/photo_images.py", line 1, in
from core.db_models import ImagesDB
File "/base/data/home/apps/s~ldsdgidev/glen27.371429613087607751/core/db_models.py", line 222, in
class UsersQuickAddForm(forms.ModelForm):#only account, firstname and last name is required
File "/base/data/home/apps/s~ldsdgidev/glen27.371429613087607751/django/forms/models.py", line 205, in new
opts.exclude, opts.widgets, formfield_callback)
File "/base/data/home/apps/s~ldsdgidev/glen27.371429613087607751/django/forms/models.py", line 145, in fields_for_model
opts = model._meta
AttributeError: type object 'UsersDB' has no attribute '_meta'
and I don't understand what I need to add to the UserDB class to get rid of the error.
Any help would be great!
This isn't anything to do with Python versions, or metaclasses.
ModelForms only work with Django models. db.Model is the App Engine model class, not the Django one. You can't use a modelform with that class.
You mention django-nonrel in your question tags. That project allows you to use the Django models - subclasses of models.Model with the App Engine datastore. You probably want to do that.
I am trying to use python-twitter api in GAE.
I need to import Oauth2 and httplib2.
Here is how I did
For OAuth2, I downloaded github.com/simplegeo/python-oauth2/tree/master/oauth2. For HTTPLib2, I dowloaded code.google.com/p/httplib2/wiki/Install and extracted folder python2/httplib2 to project root folder.
my views.py
import twitter
def index(request):
api = twitter.Api(consumer_key='XNAUYmsmono4gs3LP4T6Pw',consumer_secret='xxxxx',access_token_key='xxxxx',access_token_secret='iHzMkC6RRDipon1kYQtE5QOAYa1bVfYMhH7GFmMFjg',cache=None)
return render_to_response('fbtwitter/index.html')
I got the error paste.shehas.net/show/jbXyx2MSJrpjt7LR2Ksc
AttributeError
AttributeError: 'module' object has no attribute 'SignatureMethod_PLAINTEXT'
Traceback (most recent call last)
File "D:\PythonProj\fbtwitter\kay\lib\werkzeug\wsgi.py", line 471, in __call__
return app(environ, start_response)
File "D:\PythonProj\fbtwitter\kay\app.py", line 478, in __call__
response = self.get_response(request)
File "D:\PythonProj\fbtwitter\kay\app.py", line 405, in get_response
return self.handle_uncaught_exception(request, exc_info)
File "D:\PythonProj\fbtwitter\kay\app.py", line 371, in get_response
response = view_func(request, **values)
File "D:\PythonProj\fbtwitter\fbtwitter\views.py", line 39, in index
access_token_secret='iHzMkC6RRDipon1kYQtE5QOAYa1bVfYMhH7GFmMFjg',cache=None)
File "D:\PythonProj\fbtwitter\fbtwitter\twitter.py", line 2235, in __init__
self.SetCredentials(consumer_key, consumer_secret, access_token_key, access_token_secret)
File "D:\PythonProj\fbtwitter\fbtwitter\twitter.py", line 2264, in SetCredentials
self._signature_method_plaintext = oauth.SignatureMethod_PLAINTEXT()
AttributeError: 'module' object has no attribute 'SignatureMethod_PLAINTEXT'
It seems I did not import Oauth2 correctly when I tracked the error in twitter.py
self._signature_method_plaintext = oauth.SignatureMethod_PLAINTEXT()
I even go to twitter.py and add import oauth2 as oauth but it couldnt solve the problem
Can anybody help?
I fixed it. In twitter.py,
try:
from hashlib import md5
except ImportError:
from md5 import md5
import oauth
CHARACTER_LIMIT = 140
# A singleton representing a lazily instantiated FileCache.
DEFAULT_CACHE = object()
REQUEST_TOKEN_URL = 'https://api.twitter.com/oauth/request_token'
ACCESS_TOKEN_URL = 'https://api.twitter.com/oauth/access_token'
AUTHORIZATION_URL = 'https://api.twitter.com/oauth/authorize'
SIGNIN_URL = 'https://api.twitter.com/oauth/authenticate'
Need to change import oauth to import oauth2 as oauth
I'm using tweetpy with my GAE application and it works well.
https://github.com/tweepy/tweepy
You can find some sample codes of tweetpy on GAE in google search.
I try a simple HelloWorld with gdata, appengine and OAuth2. I read this post and the official post from Google.
Problem 1
According to the first post post, my app fails at the part 7 "Use the code to get an access token" :
Traceback (most recent call last):
File "[$PATH]/dev/outils/google_appengine/google/appengine/ext/webapp/_webapp25.py", line 701, in __call__
handler.get(*groups)
File "[$PATH]/dev/outils/google_appengine/google/appengine/ext/webapp/util.py", line 68, in check_login
handler_method(self, *args)
File "[$PATH]/dev/projets/xxx/main.py", line 76, in get
token.get_access_token(url.query)
File "[$PATH]/dev/projets/xxx/gdata/gauth.py", line 1296, in get_access_token
'redirect_uri': self.redirect_uri,
AttributeError: 'OAuth2Token' object has no attribute 'redirect_uri'
I provide the redirect_uri in the method generate_authorize_url() and i filled 2 "Redirect URIs" on Google APIs console :
http://localhost:8080/oauth2callback
http://example.com/oauth2callback
Why the redirect_uri is loosed ?
Solution : See #bossylobster answer.
Problem 2
Now, i want to save this new access token like this :
access_token_key = 'access_token_%s' % current_user.user_id()
gdata.gauth.ae_save(token, access_token_key)
Theses lines throw this exception :
Traceback (most recent call last):
File "[$PATH]/dev/outils/google_appengine/google/appengine/ext/webapp/_webapp25.py", line 701, in __call__
handler.get(*groups)
File "[$PATH]/dev/outils/google_appengine/google/appengine/ext/webapp/util.py", line 68, in check_login
handler_method(self, *args)
File "[$PATH]/dev/projets/xxx/main.py", line 89, in get
gdata.gauth.ae_save(token, access_token_key)
File "[$PATH]/dev/projets/xxx/gdata/gauth.py", line 1593, in ae_save
return gdata.alt.app_engine.set_token(key_name, token_to_blob(token))
File "[$PATH]/dev/projets/xxx/gdata/alt/app_engine.py", line 92, in set_token
if Token(key_name=unique_key, t=token_str).put():
File "[$PATH]/dev/outils/google_appengine/google/appengine/ext/db/__init__.py", line 973, in __init__
prop.__set__(self, value)
File "[$PATH]/dev/outils/google_appengine/google/appengine/ext/db/__init__.py", line 613, in __set__
value = self.validate(value)
File "[$PATH]/dev/outils/google_appengine/google/appengine/ext/db/__init__.py", line 2779, in validate
(self.name, self.data_type.__name__, err))
BadValueError: Property t must be convertible to a Blob instance (Blob() argument should be str instance, not unicode)
But gdata.gauth.access_token calls gdata.gauth.upgrade_to_access_token which return the token with some modification.
If i try with token_to_blob, i have this exception UnsupportedTokenType: Unable to serialize token of type <type 'unicode'>
** How save the new access Token ?**
main.py :
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app, login_required
from google.appengine.api import users
import gdata.gauth
import atom.http_core
SETTINGS = {
'APP_NAME': 'xxx',
'CLIENT_ID':'xxx.apps.googleusercontent.com',
'CLIENT_SECRET':'xxx',
'SCOPES': ['https://www.google.com/m8/feeds/', 'https://docs.google.com/feeds/', 'https://www.google.com/calendar/feeds/'],
'USER_AGENT' : 'xxxs',
'OAUTH2CALLBACK':'http://localhost:8080/oauth2callback'
#'OAUTH2CALLBACK':'http://example.com/oauth2callback'
}
class Home(webapp.RequestHandler):
def get(self):
"""Home"""
if users.get_current_user():
self.redirect("/step1")
else:
self.response.out.write("<a href='/step1'>Sign in google</a><br />")
class Fetcher(webapp.RequestHandler):
#login_required
def get(self):
"""This handler is responsible for fetching an initial OAuth
request token and redirecting the user to the approval page."""
current_user = users.get_current_user()
#create token
token = gdata.gauth.OAuth2Token(client_id = SETTINGS['CLIENT_ID'],
client_secret = SETTINGS['CLIENT_SECRET'],
scope = ' '.join(SETTINGS['SCOPES']),
user_agent = SETTINGS['USER_AGENT'])
url = token.generate_authorize_url(redirect_uri = SETTINGS['OAUTH2CALLBACK'])
#save token to datastore
gdata.gauth.ae_save(token, current_user.user_id())
message = """<a href="%s">
Request token for the Google Documents Scope</a>"""
self.response.out.write(message % url)
self.response.out.write(" ; redirect uri : %s" % token.redirect_uri)
class RequestTokenCallback(webapp.RequestHandler):
#login_required
def get(self):
"""When the user grants access, they are redirected back to this
handler where their authorized request token is exchanged for a
long-lived access token."""
current_user = users.get_current_user()
#get token from callback uri
url = atom.http_core.Uri.parse_uri(self.request.uri)
# get token from datastore
token = gdata.gauth.ae_load(current_user.user_id())
# SOLUTION 1
token.redirect_uri = SETTINGS['OAUTH2CALLBACK']
if isinstance(token, gdata.gauth.OAuth2Token):
if 'error' in url.query:
pass
else:
token.get_access_token(url.query)
gdata.gauth.ae_save(gdata.gauth.token_to_blob(token), "access_token_" + current_user.user_id())
def main():
application = webapp.WSGIApplication([('/', Home),
('/step1', Fetcher),
('/oauth2callback', RequestTokenCallback)],
debug = True)
run_wsgi_app(application)
if __name__ == '__main__':
main()
app.yaml :
application: xxx
version: 2
runtime: python
api_version: 1
handlers:
- url: .*
script: main.py
When you call AeLoad, you need to look at AeSave. You'll notice in the source code that token_to_blob is called.
However, in the source for token_to_blob, the redirect_uri is not saved to the blob, so you'll need to keep it around and call:
token = gdata.gauth.ae_load(current_user.user_id())
token.redirect_uri = SETTINGS['OAUTH2CALLBACK']
For reference, see another related post.
Answer to Question 2: Read the traceback: Blob() argument should be str instance, not unicode. Which version of Python are you using locally?