I want to create some entries in my database, and then render them via jinja2.
The following is my execution flow:
app = webapp2.WSGIApplication([ ('/dummy', createDummy),('/', MainPage)],debug=True)
where createDummy is:
class createDummy(webapp2.RequestHandler):
def post(self):
print("Hi! Let's post some data to db")
book1 = BooksPost(bookname="abcd",
authorname="xyz")
book1.put()
self.redirect('/')**
However, it is not going into createDummy, but is directly going to the MainPage...what could be the possible reason?
Related
I have an application running in production that I've built for a single client that I want to convert to support multiple "tenants".
Currently I am using a Postgres database where all my data resides in a single database in the default public schema. I would like to isolate each tenant to a separate Postgres schema. Ideally, my application's UI would make a call to my API using the tenant's subdomain. In before_request I would somehow be able to set all database queries during the current request context to only query that tenant's schema, is this possible?
I envisage an ideal solution to be something similar to this contrived example:
from flask import Flask, request, jsonify
from pony.orm import Database, Required
app = Flask(__name__)
db = Database(**{<db_connection_dict>})
class User(db.Entity):
email = Required(str)
password = Required(str)
#classmethod
def login(cls, email: str, password: str) -> str:
user = cls.get(lambda u: u.email.lower() == email.lower())
if not user:
return None
password_is_valid = <method_to_check_hashed_pasword>
if not password_is_valid:
return None
return <method_to_generate_jwt>
db.generate_mapping()
#app.before_request
def set_tenant():
tenant_subdomain = request.host.split(".")[0]
// MISSING STEP.. set_schema is a fictitous method, does something similar to this exist?
db.set_schema(schema=tenant_subdomain)??
#app.route("auth/login", methods=["POST"]
def login_route():
data = request.get_json()
jwt = User.login(data["email"], data["password"])
if not jwt:
return make_response({}, 403)
return make_response(jsonify(data=jwt), 200)
I've come across an interesting/simple example using SQLAlchemy. If not possible with PonyORM I may consider porting my models over to SQLAlchemy but would miss the simplicity of Pony :(
I thought about possibly using the Database.on_connect method to do something as such but not sure if if anyone has any other ideas or if this would even work properly in production. I suspect not because if I had two separate tenants querying the database they would overwrite the search path..
#db.on_connect()
def set_request_context_tenant_schema(db, connection) -> None:
subdomain = request.host.split(".")[0]
cursor = connection.cursor()
cursor.execute(f"SET search_path TO {subdomain}, public;")
I am new to Flask and bit confused about the database modeling for it. Please have my apologies if by any mean this isn't a question eligible for post.
I need to create a multi choice model field in Flask and I need to be able to access it from backend admin panel to set values for it. It does shows options in docs with WTF forms to create multiple choice field. I am confused that how to create forms attached to Database. Can someone clear it up for me because I am a Django user and in Django Forms and ModelForms have different approach so trying to understand what would it be in Flask. How to render Database based forms in Flask? How would I create a multi choice field with database created for it. Please help.
What you are looking for is SQLAlchemy built-in ORM to build forms from models or integrated to database. There are other options to overcome limitations of Flask ORM when needed. Following is the example that would give you some clarity.
from flask import Flask, render_template, redirect, flash
from flask.wtf import Form
from flask.ext.sqlalchemy import SQLAlchemy
from wtf.ext.sqlalchemy.orm import model_form
app=Flask(__app__)
app.config['SECRET_KEY'] = 'secret'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/employees.sqlite'
app.config['SQLALCHEMY_ECHO'] = True
# Here you initiate the ext
db=SQLAlchemy(app)
#Let's define a model
class Employee(db.Model)
__tablename__ = 'employee'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False
birthday = db.Column(db.Date, nullable=False
def __repr__(self):
return 'employee %s' %self.name
# Now go to your shell inside your env not in gloabal shell outside your env and run this command.
# From your .py file where you've created all above configration first make an import to db from shell
from file.py import db
#Then create a database with following command in shell
db.create.all()
#Your auto generated database based form below
EmployeeForm() = model_form(Employee, base_class=Form, field_args{'name':{'class':'employee'}})
#Let's create a view with model_form or database based form in your case.
#app.route('/', methods=['GET', 'POST'])
def index()
#request.POST does same in Django or any other Python based web framework like Bottle, Tornado etc
form = EmployeeForm()
try:
if form_validate_on_submit():
employee=Employee() #load the model values
form.populate_obj(Employee) #populates the form with respective values
db.session.add(employee) #gathers the session based data to be added in DB
db.session.commit() #Adds data to DB
flash('New Employee added to database successfully.') #Display a message to end user at front end.
retrun redirect('/') # redirects upon success to your homepage.
except Exception e:
# logs the errors
db.session.rollback()
flash('There was a problem registering new employee. Please contact the site administrator at site#site.com')
employee_list = Employe.query.all() #equailent to django style "item.objects.all() to show list of all existing items.
return render_template('index.html', form=form, employee_list=employee_list)
In last line above you did three things. You got your form variable or context variable like you do in Django as "form" so your end user can enter data.
Then you have your model data that is saved in db as "employee_list=employee_list" that will show all the list to end users. "flash" is just like Django
messaging framework.
Now for multiple choices its model has same as djagno choice arguement for key value like below:
With my experience I would suggest you to install "peewee" a simple ORM for Python connected Databases.
choices = (('key', 'value')('key', 'value'))
employee_type = db.Model(db.String(90), choices=('key1', 'key2)
Hope this helps.
I have this section of code, which is part of my Flask application. I am using flask_mongoengine.
app = Flask(__name__)
app.config.from_object('config')
db = MongoEngine(app)
from .models import *
#app.context_processor
def inject_config():
return dict(Config.objects.first(), version=version)
Config is a class within .models that extends Document.
class Config(Document):
title = StringField()
description = StringField()
keywords = StringField()
author = StringField()
version = StringField()
meta = {"collection": "web_config"}
Upon calling Config.objects, it's returning an error:
pymongo.errors.OperationFailure: database error: not authorized for query on heroku_dptwtq1j.web_config
I'm logged in through the admin user. Why am I not authorized for query? Also, how do I authorize myself to query?
I have no trouble querying through another application that uses PyMongo, so why is it not working in Flask?
If you still want to use flask_mongoengine there is a work around mentioned in https://github.com/MongoEngine/mongoengine/issues/851 which fixed it for me (though not ideal)
From allanlei:
My work around is actually to patch flask-mongoengine.connection._resolve_settings() to pass the host=mongodb://.... to mongoengine.connect()
Thanks to Chuck from mLabs who helped me find it.
So, answering my own question: the issue was probably in the flask_mongoengine library. I switched to just mongoengine and it worked fine.
I am using peewee along with flask to populate my database with user's inputs and various other stats. How can I retrieve the data in sqlite3 database?
Here is the skeleton:
from peewee import *
database = SqliteDatabase('app4.db', autocommit=True)
class BaseModel(Model):
class Meta:
database = database
class Model1(BaseModel):
class Model2(BaseModel):
class Model3(BaseModel):
app = Flask(__name__)
#app.before_request
def func1():
database.connect()
#app.after_request
def func2(response):
database.close()
return response
#app.route('/', method= ['GET'])
def some_func():
#update pluto and create instances of Model2 and Model3 here
if __name__ == "__main__":
database.connect()
database.create_tables([Model1, Model2, Model3], True)
pluto, created = Model1.get_or_create(key = 2, key2 = 0)
My app is running and showing the updated instances of Model1 and Model2 which means that it has created the models and is continually updating the database.
But I don't know how to retrieve this data offline.
When I enter my sqllite database by sqlite3 app4.db and type .tables it shows me all the tables i.e. Model1, Model2, Model3 but typing in the query : select * from model1; gives nothing. I tried retrieving the data in Ipython shell too making a connection to database as above and querying list(Model1.select()) but it gives an empty list.
It looks like your database filename is being set to app.py:
database = SqliteDatabase('app.py', autocommit=True)
It should probably be app4.db if that's what you want to use:
database = SqliteDatabase('app4.db', autocommit=True)
The commands you are using look like the correct ones for doing it at the command line. Sounds to me like either 1 of 2 things are happening:
You are not actually putting data into the databases
You are not viewing the same database that you are populating.
Try renaming the app4.db file, and re-running your app and see if it creates a new one. This way you can make sure you are using sqlite3 on the correct one. If you are still not seeing any data using the commands you listed, I would assume that your app is not actually putting the data into the tables.
I'm working on an ecommerce website, using Google App Engine with Python. Now, since its an ecommerce website, we would be having dozens of products displayed, each having its own webpage. Now, my question is, if we have about 400 web pages on our server, won't it make the site pretty heavy and bulky? Won't that affect the user experience?
How can we manage the 400-odd web pages on Google App Engine? Is there something I don't know about making a web application less bulky in spite of hosting multiple web pages on the server?
You can use webapp2 framework and fetch product info from the datastore and render it with a template. You make an entity for your product e.g.
class Product(db.Model):
tags = db.ListProperty(db.Category)
category = db.CategoryProperty(verbose_name='Category')
title = db.StringProperty(verbose_name='title') # required
text = db.TextProperty(verbose_name='text')
Then you have a handler class using webapp2, flask, bottle or similar to fetch your product data and render it with for instance the jinja 2 templating engine.
class ProductHandler(BaseHandler):
def get_product(self, key):
data = memcache.get(key)
if data is not None:
return data
else:
data = Product.get_by_id(long(key))
memcache.add(key, data, 6000)
return data
def get(self, id, html):
product= self.get_product(id)
if not product:
self.error(404)
return
self.render_jinja(
'view_product',
product=product)
Then in your template you can use the variables on the view_product.html e.g.
{{product.title}
And the routing is done with a config object for webapp2 (this will be different if you use flask or bottle but if you use flask or bottle you can't leverage webapp2's extras such as User models and i18n)
app = webapp2.WSGIApplication([('/view/(\d+)(\.html?)?', ProductHandler),