query in datastore without a model - python-2.7

I am trying to create an application in appengine that searches for a list of keys and then I use this list to delete these records from the datastore, this service has to be a generic service so I could not use a model just search by the name of kind, it is possible to do this through appengine features?
Below my code, but it requires that I have a model.
import httplib
import logging
from datetime import datetime, timedelta
import webapp2
from google.appengine.api import urlfetch
from google.appengine.ext import ndb
DEFAULT_PAGE_SIZE = 100000
DATE_PATTERN = "%Y-%m-%dT%H:%M:%S"
def get_date(amount):
date = datetime.today() - timedelta(days=30 * amount)
date = date.replace(hour=0, minute=0, second=0)
return date
class Purge(webapp2.RequestHandler):
def get(self):
kind = self.request.get('kind')
datefield = self.request.get('datefield')
amount = self.request.get('amount', default_value=3)
date = get_date(amount)
logging.info('Executando purge para Entity {}, mantendo periodo de {} meses.'.format(kind, amount))
# cria a query
query = ndb.Query(kind=kind, namespace='development')
logging.info('Setando o filtro [{} <= {}]'.format(datefield, date.strftime(DATE_PATTERN)))
# cria um filtro
query.filter(ndb.DateTimeProperty(datefield) <= date)
query.fetch_page(DEFAULT_PAGE_SIZE)
while True:
# executa a consulta
keys = query.fetch(keys_only=True)
logging.info('Encontrados {} {} a serem exluidos'.format(len(keys), kind))
# exclui usando as keys
ndb.delete_multi(keys)
if len(keys) < DEFAULT_PAGE_SIZE:
logging.info('Nao existem mais registros a serem excluidos')
break
app = webapp2.WSGIApplication(
[
('/cloud-datastore-purge', Purge),
], debug=True)
Trace
Traceback (most recent call last):
File "/base/alloc/tmpfs/dynamic_runtimes/python27g/7894e0c59273b2b7/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1535, in __call__
rv = self.handle_exception(request, response, e)
File "/base/alloc/tmpfs/dynamic_runtimes/python27g/7894e0c59273b2b7/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1529, in __call__
rv = self.router.dispatch(request, response)
File "/base/alloc/tmpfs/dynamic_runtimes/python27g/7894e0c59273b2b7/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1278, in default_dispatcher
return route.handler_adapter(request, response)
File "/base/alloc/tmpfs/dynamic_runtimes/python27g/7894e0c59273b2b7/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1102, in __call__
return handler.dispatch()
File "/base/alloc/tmpfs/dynamic_runtimes/python27g/7894e0c59273b2b7/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 572, in dispatch
return self.handle_exception(e, self.app.debug)
File "/base/alloc/tmpfs/dynamic_runtimes/python27g/7894e0c59273b2b7/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 570, in dispatch
return method(*args, **kwargs)
File "/base/data/home/apps/p~telefonica-dev-155211/cloud-datastore-purge-python:20180629t150020.410785498982375644/purge.py", line 38, in get
query.fetch_page(_DEFAULT_PAGE_SIZE)
File "/base/alloc/tmpfs/dynamic_runtimes/python27g/7894e0c59273b2b7/python27/python27_lib/versions/1/google/appengine/ext/ndb/utils.py", line 160, in positional_wrapper
return wrapped(*args, **kwds)
File "/base/alloc/tmpfs/dynamic_runtimes/python27g/7894e0c59273b2b7/python27/python27_lib/versions/1/google/appengine/ext/ndb/query.py", line 1362, in fetch_page
return self.fetch_page_async(page_size, **q_options).get_result()
File "/base/alloc/tmpfs/dynamic_runtimes/python27g/7894e0c59273b2b7/python27/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 383, in get_result
self.check_success()
File "/base/alloc/tmpfs/dynamic_runtimes/python27g/7894e0c59273b2b7/python27/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 427, in _help_tasklet_along
value = gen.throw(exc.__class__, exc, tb)
File "/base/alloc/tmpfs/dynamic_runtimes/python27g/7894e0c59273b2b7/python27/python27_lib/versions/1/google/appengine/ext/ndb/query.py", line 1380, in _fetch_page_async
while (yield it.has_next_async()):
File "/base/alloc/tmpfs/dynamic_runtimes/python27g/7894e0c59273b2b7/python27/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 427, in _help_tasklet_along
value = gen.throw(exc.__class__, exc, tb)
File "/base/alloc/tmpfs/dynamic_runtimes/python27g/7894e0c59273b2b7/python27/python27_lib/versions/1/google/appengine/ext/ndb/query.py", line 1793, in has_next_async
yield self._fut
File "/base/alloc/tmpfs/dynamic_runtimes/python27g/7894e0c59273b2b7/python27/python27_lib/versions/1/google/appengine/ext/ndb/context.py", line 890, in helper
batch, i, ent = yield inq.getq()
File "/base/alloc/tmpfs/dynamic_runtimes/python27g/7894e0c59273b2b7/python27/python27_lib/versions/1/google/appengine/ext/ndb/query.py", line 969, in run_to_queue
batch = yield rpc
File "/base/alloc/tmpfs/dynamic_runtimes/python27g/7894e0c59273b2b7/python27/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 513, in _on_rpc_completion
result = rpc.get_result()
File "/base/alloc/tmpfs/dynamic_runtimes/python27g/7894e0c59273b2b7/python27/python27_lib/versions/1/google/appengine/api/apiproxy_stub_map.py", line 613, in get_result
return self.__get_result_hook(self)
File "/base/alloc/tmpfs/dynamic_runtimes/python27g/7894e0c59273b2b7/python27/python27_lib/versions/1/google/appengine/datastore/datastore_query.py", line 2951, in __query_result_hook
self.__results = self._process_results(query_result.result_list())
File "/base/alloc/tmpfs/dynamic_runtimes/python27g/7894e0c59273b2b7/python27/python27_lib/versions/1/google/appengine/datastore/datastore_query.py", line 2984, in _process_results
for result in results]
File "/base/alloc/tmpfs/dynamic_runtimes/python27g/7894e0c59273b2b7/python27/python27_lib/versions/1/google/appengine/datastore/datastore_rpc.py", line 194, in pb_to_query_result
return self.pb_to_entity(pb)
File "/base/alloc/tmpfs/dynamic_runtimes/python27g/7894e0c59273b2b7/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 690, in pb_to_entity
modelclass = Model._lookup_model(kind, self.default_model)
File "/base/alloc/tmpfs/dynamic_runtimes/python27g/7894e0c59273b2b7/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 3101, in _lookup_model
kind)
KindError: No model class found for kind 'Test'. Did you forget to import it?

The problem was found on the line where fetch_page is set.
Removing this line
query.fetch_page(DEFAULT_PAGE_SIZE)
for this
keys = query.fetch(limit=_DEFAULT_LIMIT, keys_only=True)

To run a datastore query without a model class available in the environment, you can use the google.appengine.api.datastore.Query class from the low-level datastore API.
See this question for other ideas.

If the goal is simply to wipe entities regardless of their kind then you have some options besides specifying the kinds/models yourself.
you could obtain the list of all kinds from your models file and iterate through them, see How to delete all the entries from google datastore?
using the generic datastore client library (not ndb) you could obtain the list of kinds from the datastore itself, see
Is there a way to delete all entities from a Datastore namespace Using Python3 (WITHOUT Dataflow)? But I vaguely remember some issues which might translate to that library not working on the 1st generation standard environment anymore, so I'm not 100% certain of this.

Related

How to specify SQLAlchemy ForeignKey with specific schema name?

I have a Flask / Flask-User app that I am trying to convert from Python 3.6 to Flask / Flask-Security-Too under Python 3.10. There have been a lot of changes in the world since 3.6 and I am playing whack-a-mole trying to figure them out. In this particular case I am redoing the database tables since nothing from the old app needs to transfer to the new version. I am using the latest version of PyCharm and all of the latest versions of the libraries that Flask and Flask-Security-Too require.
Things to note: the target database is an MS SQL Server instance. There is an existing "database" that I must use and a specific "schema name" under which any tables I create must live.
I have successfully run flask db init and am trying to run the first flask db migrate but get the error:
(venv) PS C:\Users\me\PycharmProjects\MyProject\UserInterface\MyApp> flask db migrate
INFO [alembic.runtime.migration] Context impl MSSQLImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
Traceback (most recent call last):
File "C:\Python310\lib\runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "C:\Python310\lib\runpy.py", line 86, in _run_code
exec(code, run_globals)
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\Scripts\flask.exe\__main__.py", line 7, in <module>
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\flask\cli.py", line 988, in main
cli.main()
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\flask\cli.py", line 579, in main
return super().main(*args, **kwargs)
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\click\core.py", line 1055, in main
rv = self.invoke(ctx)
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\click\core.py", line 1657, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\click\core.py", line 1657, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\click\core.py", line 1404, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\click\core.py", line 760, in invoke
return __callback(*args, **kwargs)
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\click\decorators.py", line 26, in new_func
return f(get_current_context(), *args, **kwargs)
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\flask\cli.py", line 427, in decorator
return __ctx.invoke(f, *args, **kwargs)
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\click\core.py", line 760, in invoke
return __callback(*args, **kwargs)
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\flask_migrate\cli.py", line 104, in migrate
_migrate(directory, message, sql, head, splice, branch_label, version_path,
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\flask_migrate\__init__.py", line 98, in wrapped
f(*args, **kwargs)
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\flask_migrate\__init__.py", line 155, in migrate
command.revision(config, message, autogenerate=True, sql=sql,
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\alembic\command.py", line 229, in revision
script_directory.run_env()
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\alembic\script\base.py", line 569, in run_env
util.load_python_file(self.dir, "env.py")
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\alembic\util\pyfiles.py", line 94, in load_python_file
module = load_module_py(module_id, path)
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\alembic\util\pyfiles.py", line 110, in load_module_py
spec.loader.exec_module(module) # type: ignore
File "<frozen importlib._bootstrap_external>", line 883, in exec_module
File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\MyApp\migrations\env.py", line 104, in <module>
run_migrations_online()
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\MyApp\migrations\env.py", line 98, in run_migrations_online
context.run_migrations()
File "<string>", line 8, in run_migrations
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\alembic\runtime\environment.py", line 853, in run_migrations
self.get_context().run_migrations(**kw)
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\alembic\runtime\migration.py", line 611, in run_migrations
for step in self._migrations_fn(heads, self):
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\alembic\command.py", line 205, in retrieve_migrations
revision_context.run_autogenerate(rev, context)
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\alembic\autogenerate\api.py", line 526, in run_autogenerate
self._run_environment(rev, migration_context, True)
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\alembic\autogenerate\api.py", line 573, in _run_environment
compare._populate_migration_script(
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\alembic\autogenerate\compare.py", line 55, in _populate_migration_script
_produce_net_changes(autogen_context, upgrade_ops)
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\alembic\autogenerate\compare.py", line 89, in _produce_net_changes
comparators.dispatch("schema", autogen_context.dialect.name)(
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\alembic\util\langhelpers.py", line 267, in go
fn(*arg, **kw)
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\alembic\autogenerate\compare.py", line 125, in _autogen_for_tables
[(table.schema, table.name) for table in autogen_context.sorted_tables]
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\sqlalchemy\util\langhelpers.py", line 1113, in __get__
obj.__dict__[self.__name__] = result = self.fget(obj)
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\alembic\autogenerate\api.py", line 443, in sorted_tables
result.extend(m.sorted_tables)
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\sqlalchemy\sql\schema.py", line 4697, in sorted_tables
return ddl.sort_tables(
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\sqlalchemy\sql\ddl.py", line 1213, in sort_tables
for (t, fkcs) in sort_tables_and_constraints(
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\sqlalchemy\sql\ddl.py", line 1291, in sort_tables_and_constraints
dependent_on = fkc.referred_table
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\sqlalchemy\sql\schema.py", line 3808, in referred_table
return self.elements[0].column.table
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\sqlalchemy\util\langhelpers.py", line 1113, in __get__
obj.__dict__[self.__name__] = result = self.fget(obj)
File "C:\Users\me\PycharmProjects\MyProject\UserInterface\venv\lib\site-packages\sqlalchemy\sql\schema.py", line 2507, in column
raise exc.NoReferencedTableError(
sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 'roles_users.role_id' could not find table 'role' with which to generate a foreign key to target column 'id'
The User and Role models look like (pruned for length):
### USER
#
import uuid
from flask_security import UserMixin
from sqlalchemy import Column, Integer, String, Boolean, Unicode, DateTime, func
from sqlalchemy.orm import relationship, backref
from app.database import Base
class User(Base, UserMixin):
__tablename__ = 'user'
__table_args__ = {"schema": "ExistingSchemaName"}
id = Column(Integer,primary_key=True)
email = Column(Unicode(255),nullable=False,server_default=u'',unique=True)
...
# Flask-Security-Too fields
fs_uniquifier = Column(String(255), unique=True, nullable=False)
confirmed_at = Column(DateTime())
last_login_at = Column(DateTime())
current_login_at = Column(DateTime())
last_login_ip = Column(String(100))
current_login_ip = Column(String(100))
login_count = Column(Integer)
# Relationships
child_roles = relationship('Role',back_populates='parent_user')
import uuid
### ROLE
#
from flask_security import RoleMixin
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship
from app.database import Base
class Role(Base, RoleMixin):
__tablename__ = 'role'
__table_args__ = {"schema": "ExistingSchemaName"}
id = Column(Integer(),primary_key=True)
name = Column(String(64),nullable=False,server_default=u'',unique=True)
description = Column(String(255),nullable=False,server_default=u'')
# Have also tried adding schema name to ForeignKey without success, as in:
# user_id = Column(Integer,ForeignKey("ExistingSchemaName.user.id"))
user_id = Column(Integer,ForeignKey("user.id"))
parent_user = relationship("User",back_populates="child_roles")
The app.database.py file looks like:
from .settings import SQLALCHEMY_DATABASE_URI
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
engine = create_engine(SQLALCHEMY_DATABASE_URI)
db = scoped_session(
sessionmaker(
autocommit=False,
autoflush=False,
bind=engine
)
)
Base = declarative_base()
Base.query = db.query_property()
def init_db():
import app.models
Base.metadata.create_all(bind=engine)
I think that I have set the one-to-many relationships correctly but I do not know what I am missing.

app engine standard environment call bigquery python

I am trying to deploy a simple standard app engine in python and from there to make bigquery queries through python bigquery client.
The code is as simple as these:
from __future__ import absolute_import
import webapp2
import os
from google.cloud import bigquery
class MainPage(webapp2.RequestHandler):
def get(self):
client = bigquery.Client(project = "ancient-ceiling-125223")
project_name = str(client.project)
query_job = client.query("select 1")
assert query_job.state == 'RUNNING'
iterator = query_job.result(timeout= 30)
rows = list(iterator)
self.response.write('nothing to see %s' % (project_name))
app = webapp2.WSGIApplication(
[('/', MainPage)], debug=True)
The error log: The error appears in the dummy query request
*('Connection broken: IncompleteRead(209 bytes read)', IncompleteRead(209 bytes read)) (/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.3/webapp2.py:1528)
Traceback (most recent call last):
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.3/webapp2.py", line 1511, in __call__
rv = self.handle_exception(request, response, e)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.3/webapp2.py", line 1505, in __call__
rv = self.router.dispatch(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.3/webapp2.py", line 1253, in default_dispatcher
return route.handler_adapter(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.3/webapp2.py", line 1077, in __call__
return handler.dispatch()
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.3/webapp2.py", line 547, in dispatch
return self.handle_exception(e, self.app.debug)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.3/webapp2.py", line 545, in dispatch
return method(*args, **kwargs)
File "/base/data/home/apps/s~ancient-ceiling-125223/20171115t104156.405543624689752939/main.py", line 35, in get
query_job = client.query("select 1")
File "/base/data/home/apps/s~ancient-ceiling-125223/20171115t104156.405543624689752939/lib/google/cloud/bigquery/client.py", line 986, in query
job._begin(retry=retry)
File "/base/data/home/apps/s~ancient-ceiling-125223/20171115t104156.405543624689752939/lib/google/cloud/bigquery/job.py", line 397, in _begin
method='POST', path=path, data=self._build_resource())
File "/base/data/home/apps/s~ancient-ceiling-125223/20171115t104156.405543624689752939/lib/google/cloud/bigquery/client.py", line 271, in _call_api
return call()
File "/base/data/home/apps/s~ancient-ceiling-125223/20171115t104156.405543624689752939/lib/google/api_core/retry.py", line 260, in retry_wrapped_func
on_error=on_error,
File "/base/data/home/apps/s~ancient-ceiling-125223/20171115t104156.405543624689752939/lib/google/api_core/retry.py", line 177, in retry_target
return target()
File "/base/data/home/apps/s~ancient-ceiling-125223/20171115t104156.405543624689752939/lib/google/cloud/_http.py", line 290, in api_request
headers=headers, target_object=_target_object)
File "/base/data/home/apps/s~ancient-ceiling-125223/20171115t104156.405543624689752939/lib/google/cloud/_http.py", line 183, in _make_request
return self._do_request(method, url, headers, data, target_object)
File "/base/data/home/apps/s~ancient-ceiling-125223/20171115t104156.405543624689752939/lib/google/cloud/_http.py", line 212, in _do_request
url=url, method=method, headers=headers, data=data)
File "/base/data/home/apps/s~ancient-ceiling-125223/20171115t104156.405543624689752939/lib/google/auth/transport/requests.py", line 186, in request
method, url, data=data, headers=request_headers, **kwargs)
File "/base/data/home/apps/s~ancient-ceiling-125223/20171115t104156.405543624689752939/lib/requests/sessions.py", line 502, in request
resp = self.send(prep, **send_kwargs)
File "/base/data/home/apps/s~ancient-ceiling-125223/20171115t104156.405543624689752939/lib/requests/sessions.py", line 652, in send
r.content
File "/base/data/home/apps/s~ancient-ceiling-125223/20171115t104156.405543624689752939/lib/requests/models.py", line 825, in content
self._content = bytes().join(self.iter_content(CONTENT_CHUNK_SIZE)) or bytes()
File "/base/data/home/apps/s~ancient-ceiling-125223/20171115t104156.405543624689752939/lib/requests/models.py", line 750, in generate
raise ChunkedEncodingError(e)
ChunkedEncodingError: ('Connection broken: IncompleteRead(209 bytes read)', IncompleteRead(209 bytes read))*
I could not make it work using python bigquery client library, Here is what I found working in standard app engine environment,
from __future__ import absolute_import
import webapp2
from googleapiclient.discovery import build
from oauth2client.client import GoogleCredentials
class MainPage(webapp2.RequestHandler):
def get(self):
credentials = GoogleCredentials.get_application_default()
service = build('bigquery', 'v2', credentials=credentials)
datasets = service.datasets().list(projectId="ancient-ceiling-125223").execute()
self.response.write('datasets: %s' % datasets)
app = webapp2.WSGIApplication(
[('/', MainPage)], debug=True)

How to create the tables in a model FlaskDB with peewee?

Going off the documentation here.
I have this code:
from playhouse.flask_utils import FlaskDB,
app = Flask(__name__)
app.config.from_object(__name__)
flask_db = FlaskDB(app)
database = flask_db.database
class Item(flask_db.Model):
title = CharField()
content = TextField()
category = CharField()
#app.route('/create',methods=('GET','POST'))
def create():
if request.method == 'POST':
if request.form.get('title') and request.form.get('content'):
item = Item.create(
title = request.form['title'],
content = request.form['content'],
category = request.form['category'])
flash('Item created successfully','success')
return redirect(url_for('view'),item=item)
else:
flash('Title and Content are required.','danger')
form = ItemForm()
return render_template('create.html',form=form)
if __name__ == '__main__':
database.create_tables(Item)
app.run(debug=True)
They say it:
Dynamically create a Peewee database instance based on app config data.
However, I believe I still need to create the tables, in fact when I tried it without doing that second to last line, I could see that no tables existed in the created blog.db file. Unfortunately when I run this now, I get:
Traceback (most recent call last):
sqliteext:////Users/conduce-laptop/PycharmProjects/alexmarshall.website/blog.db
File "/Users/conduce-laptop/PycharmProjects/alexmarshall.website/website2.py", line 73, in <module>
database.create_tables(Item)
File "/Users/conduce-laptop/anaconda2/lib/python2.7/site-packages/peewee.py", line 3855, in create_tables
create_model_tables(models, fail_silently=safe)
File "/Users/conduce-laptop/anaconda2/lib/python2.7/site-packages/peewee.py", line 5293, in create_model_tables
for m in sort_models_topologically(models):
File "playhouse/_speedups.pyx", line 341, in playhouse._speedups.sort_models_topologically (playhouse/_speedups.c:7091)
File "/Users/conduce-laptop/anaconda2/lib/python2.7/site-packages/peewee.py", line 4862, in __iter__
return iter(self.select())
File "/Users/conduce-laptop/anaconda2/lib/python2.7/site-packages/peewee.py", line 3240, in __iter__
return iter(self.execute())
File "/Users/conduce-laptop/anaconda2/lib/python2.7/site-packages/peewee.py", line 3233, in execute
self._qr = ResultWrapper(model_class, self._execute(), query_meta)
File "/Users/conduce-laptop/anaconda2/lib/python2.7/site-packages/peewee.py", line 2912, in _execute
return self.database.execute_sql(sql, params, self.require_commit)
File "/Users/conduce-laptop/anaconda2/lib/python2.7/site-packages/peewee.py", line 3775, in execute_sql
self.commit()
File "/Users/conduce-laptop/anaconda2/lib/python2.7/site-packages/peewee.py", line 3598, in __exit__
reraise(new_type, new_type(*exc_args), traceback)
File "/Users/conduce-laptop/anaconda2/lib/python2.7/site-packages/peewee.py", line 3768, in execute_sql
cursor.execute(sql, params or ())
peewee.OperationalError: no such table: item
You were invoking the create_tables incorrectly:
database.create_tables([Item], True)
The True allows you to call it multiple times without errors.
I had to run: Item.create_table(fail_silently=True) in in the very Bottom instead of database.create_tables(Item). Apparently you just run it once (since you wouldn't want to recreate the table

error serializaing GAE session with webapp2_extras

I am not new to App Engine, but am just getting started with the Python stack on it. I am using webapp2 and Cygwin with its own Python. I am trying to implement custom authentication, relying on sessions.. I am following numerous examples of enabling sessions using webapp2-extras module. I have the following relevant code:
import webapp2
from webapp2_extras import sessions
class BaseHandler(webapp2.RequestHandler):
def dispatch(self):
self.session_store = sessions.get_store(request=self.request)
try:
webapp2.RequestHandler.dispatch(self)
finally:
self.session_store.save_sessions(self.response)
#webapp2.cached_property
def session(self):
return self.session_store.get_session(self.response, backend='datastore')
class CounterHandler(BaseHandler):
def get(self):
cnt_key = 'cnt'
if cnt_key in self.session:
cnt = int(self.session[cnt_key])
else:
cnt = 0
cnt += 1
self.session[cnt_key] = str(cnt)
self.response.headers['Content-Type'] = 'text/plain'
self.response.write("Hello, world!")
This fails with the following stack trace:
Traceback (most recent call last):
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1535, in __call__
rv = self.handle_exception(request, response, e)
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1529, in __call__
rv = self.router.dispatch(request, response)
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1278, in default_dispatcher
return route.handler_adapter(request, response)
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1102, in __call__
return handler.dispatch()
File "/cygdrive/c/Documents and Settings/dev/My Documents/proj/easytime_gae/src/handlers.py", line 11, in dispatch
self.session_store.save_sessions(self.response)
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2_extras/sessions.py", line 420, in save_sessions
session.save_session(response)
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2_extras/appengine/sessions_ndb.py", line 117, in save_session
response, self.name, {'_sid': self.sid}, **self.session_args)
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2_extras/sessions.py", line 423, in save_secure_cookie
value = self.serializer.serialize(name, value)
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2_extras/securecookie.py", line 48, in serialize
signature = self._get_signature(name, value, timestamp)
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2_extras/securecookie.py", line 103, in _get_signature
signature.update('|'.join(parts))
TypeError: sequence item 0: expected string, Response found
The error goes away if I disable the line that writes to the session object and leave reading from sessions intact:
# self.session[cnt_key] = str(cnt)
Any help would be much appreciated.
The first argument to get_session is the name, if you want to change from the default. You are passing a response object, which is wrong.
#webapp2.cached_property
def session(self):
return self.session_store.get_session(backend='datastore')

Attribute error for list of objects from collection?

We're using Flask-Restful for implementing an API. As database we use MongoDB and MongoEngine as ODM. To get MongoEngine to work with Restful, we followed this blog article. For getting the correct json-format we using the builtin marsheling-methods. This works perfectly for single objects (e.g. one item of a collection), but when marsheling a list of objects (e.g. all items of a collection), an AttributeError is raised (although we use the same syntax as for single objects). This is how our model and our views look like (I don't paste the routes, as they are in a separate file and work).
model:
class Task(db.Document):
name = db.StringField()
description_mini = db.StringField()
views:
parser = reqparse.RequestParser()
parser.add_argument('task_id', type=str)
task_format = {
"name": fields.String,
"description_mini": fields.String
}
class TasksView(Resource):
#marshal_with(task_format)
def get(self):
tasks = Task.objects().all()
return tasks, 200
class TaskDetailView(Resource):
#marshal_with(task_format)
def get(self):
args = parser.parse_args()
startup_id = args['task_id']
task = Task.objects(id=task_id).first()
return task, 200
full stacktrace:
AttributeError
Traceback (most recent call last)
File "/project/venv/lib/python2.7/site-packages/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "/project/venv/lib/python2.7/site-packages/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/project/venv/lib/python2.7/site-packages/flask_restful/__init__.py", line 257, in error_router
return self.handle_error(e)
File "/project/venv/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/project/venv/lib/python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/project/venv/lib/python2.7/site-packages/flask_restful/__init__.py", line 257, in error_router
return self.handle_error(e)
File "/project/venv/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/project/venv/lib/python2.7/site-packages/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/project/venv/lib/python2.7/site-packages/flask_restful/__init__.py", line 397, in wrapper
resp = resource(*args, **kwargs)
File "/project/venv/lib/python2.7/site-packages/flask/views.py", line 84, in view
return self.dispatch_request(*args, **kwargs)
File "/project/venv/lib/python2.7/site-packages/flask_restful/__init__.py", line 487, in dispatch_request
resp = meth(*args, **kwargs)
File "/project/venv/lib/python2.7/site-packages/flask_restful/__init__.py", line 562, in wrapper
return marshal(data, self.fields), code, headers
File "/project/venv/lib/python2.7/site-packages/flask_restful/__init__.py", line 533, in marshal
return OrderedDict(items)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/collections.py", line 52, in __init__
self.__update(*args, **kwds)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/_abcoll.py", line 547, in update
for key, value in other:
File "/project/venv/lib/python2.7/site-packages/flask_restful/__init__.py", line 532, in <genexpr>
for k, v in fields.items())
File "/project/venv/lib/python2.7/site-packages/flask_restful/fields.py", line 104, in output
value = get_value(key if self.attribute is None else self.attribute, obj)
File "/project/venv/lib/python2.7/site-packages/flask_restful/fields.py", line 37, in get_value
return _get_value_for_keys(key.split('.'), obj, default)
File "/project/venv/lib/python2.7/site-packages/flask_restful/fields.py", line 42, in _get_value_for_keys
return _get_value_for_key(keys[0], obj, default)
File "/project/venv/lib/python2.7/site-packages/flask_restful/fields.py", line 51, in _get_value_for_key
return obj[key]
File "/project/venv/lib/python2.7/site-packages/mongoengine/queryset/base.py", line 152, in __getitem__
raise AttributeError
AttributeError
When you want to marshal a list you have to define the fields as a list as well.
I think this will work:
task_list_format = {
'tasks': fields.List(fields.Nested(task_format))
}
class TasksView(Resource):
#marshal_with(task_list_format)
def get(self):
tasks = Task.objects().all()
return { 'tasks': tasks }, 200
I believe it is not possible to return a plain list using the marshaling support in Flask-RESTful, it always expects a dictionary. For that reason I put the list under a "tasks" key.
I hope this helps.
From what I understand, the problem is that mongoengine's Queryset object lazily queries the database and that Flask-restful/restplus marshalling expects a list.
I could make it work with
task_format = {
"name": fields.String,
"description_mini": fields.String
}
class TasksView(Resource):
#marshal_with(task_format)
def get(self):
tasks = Task.objects().all()
return list(tasks)
try flask_restful.marshal_with_fields:
>>> from flask_restful import marshal_with_field, fields
>>> #marshal_with_field(fields.List(fields.Integer))
... def get():
... return ['1', 2, 3.0]
...
>>> get()
[1, 2, 3]