How to run flask and mongoengine with a remote host? - python

I am following this example here:
http://docs.mongodb.org/manual/tutorial/write-a-tumblelog-application-with-flask-mongoengine/
My problem lies here:
from flask import Flask
from flask.ext.mongoengine import MongoEngine
app = Flask(__name__)
app.config["MONGODB_DB"] = "my_tumble_log"
app.config["SECRET_KEY"] = "KeepThisS3cr3t"
db = MongoEngine(app)
if __name__ == '__main__':
app.run()
This assumes that the MONGODB_DB is "my_tumble_log" on my local machine and default port. What if my mongo database is on a remote machine with a different port? How would I modify the example to allow this?
I have tried adding a line before the MONGODB_DB app.config:
app.config['MONGODB_CONNSTRING'] = "mongodb://myremotehost:myport"
Though it has no effect whatsoever.

The following configuration settings are available:
MONGODB_DB
MONGODB_USERNAME
MONGODB_PASSWORD
MONGODB_HOST
MONGODB_PORT

Related

Config var does not work in python Heroku app

I have an application that uses some environments variables like host, users, dbname to protect sensive data in a database connection. In local ambient, using localhost with Pycharm IDE that works fine!!! But when I upload code to Heroku, it don´t recognize my environment variables and app crashes.
Here is small code showing how I call variables at Pycharm IDE. That is fine for localhost:
from flask.app import Flask
from flask.templating import render_template
from flask_socketio import SocketIO, emit, send
import os
app = Flask(__name__)
host = os.environ['HOST']
dbname = os.environ['dbname']
#app.route("/")
def home():
return('<div>Host: ' + host + '</div><div>Dbname: ' + dbname + '</div>'
)
if __name__ == "__main__":
#io.run(app, debug=False)
app.run()
Here is response in local browser, that´s ok!
enter image description here
In Heroko, config var are equal variables above, follow print os settings:
Here is the result of same code uploaded to Heroku
enter image description here
And here is the return of logs --tail from heroku
enter image description here
enter image description here
Well, any suggestions to solve this problem? How can I adapt code to run in Heroku app?
Thx

flask_sqlalchemy keeps trying to connect to localhost database instead of the remote one

I'm trying to use the flask_sqlalchemy library in order to connect to a PostgreSQL server on my remote Ubuntu machine, but my app keeps trying to connect to the localhost database instead of the remote one. I don't have got any databases installed locally and there is no difference what I put in the SQLALCHEMY_DATABASE_URI variable.
All similar questions have no answer on stack overflow, so I despaired, guys.
Thx in advance!
Here is my config (I'm running it on MacOS):
import os
import connexion
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
basedir = os.path.abspath(os.path.dirname(__file__))
connex_app = connexion.App(__name__, specification_dir=basedir)
app = connex_app.app
app.config["SQLALCHEMY_ECHO"] = False
app.config[
"SQLALCHEMY_DATABASE_URI"
] = "postgresql://login:password#serverIP:port/dbName"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)
ma = Marshmallow(app)

How to initialise multiple database engines for while starting a python-flask application?

I am working on a python-flask application where I initialise database engines at the time starting the server. This is how my app.py file looks like.
import statements
from dbmanager import datasource
app = Flask(__name__)
CORS(app)
app.secret_key = 'bob'
api = Api(app)
HERE = Path(__file__).parent
for api_class_file in HERE.glob("apis/*.py"):
api_class_name = api_class_file.stem
api_module = import_module(f"apis.{api_class_name}")
api_class = getattr(api_module, api_class_name)
if api_class_name != '__init__':
api.add_resource(api_class, f"/{api_class_name}".lower())
app.ls_sf_db_env = 'prod'
app.ls_config = config_reader.get_config('prod')
# Initialise the connection pool
datasource.initialize_all_site_engines(app)
if __name__ == '__main__':
app.run(host='127.0.0.1', port=5000)
app.run(debug=True)
I prepared the datasource file to and used SQLAlchemy to create & initialise multiple engines for different connections as below:
from flask import current_app
from sqlalchemy import create_engine
site_name = {"AP":"DBAP10", "GL":"DBGL10"}
def lookup(site):
return current_app.ls_db_connection_pool[site]
def initialize_all_site_engines(app):
conf, sf_db_env = app.ls_config, app.ls_sf_db_env
ls_db_connection_pool = {}
if sf_db_env == 'test':
engine = create_connection_pool('AP')
ls_db_connection_pool['AP'] = engine
ls_db_connection_pool['GL'] = engine
else:
ls_db_connection_pool['AP'] = create_connection_pool('AP')
ls_db_connection_pool['GL'] = create_connection_pool('GL')
app.ls_db_connection_pool = ls_db_connection_pool
def create_connection_pool(site):
print(f'Creating Engine for: {site}')
username = 'username'
password = 'password'
host = 'host'
dbname = site_name[site]
url = f"mssql+pymssql://{username}:{password}#{host}/{dbname}"
engine = create_engine(url, encoding='utf-8', max_overflow=3, pool_size=5, pool_recycle=3600)
return engine
If the value of sf_db_env is not test I am initialising multiple production engines for the respective databases. In our project, we have multiple sites with multiple databases as below:
For example: AP is a site with database: DBAP10. FS is a site with database: DBFS10
When I start the server as python app.py I see this log on my terminal:
Creating Engine for: DBAP10
engine created for AP
Creating Engine for: DBGL10
engine created for GL
* Serving Flask app "app" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
2020-12-03 14:38:18,392 - _internal - INFO - * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
And in my API class, I am using
engine = datasource.lookup('AP')
connection = engine.connect()
do_something_with_connection
I cannot test my code for multiple sites/databases as we only have the database set up for the site 'AP' at the moment. But the multiple site environment is going to come in 2021 & we're told to configure connection parameters as such right now
Could anyone let me know if the way I am creating multiple engines while the server starts is the right way to do ? Any help is much appreciated.
Well, i can't really tell you if the way you are doing this is the correct one, but i recommend using docker/docker-compose to create some database/site dummies and test it yourself.

How do I mock PyMongo for testing with a Flask app?

I've found similar questions, but they seem to only cover mocking MongoDB and don't mention Flask.
I have a Flask app and I'm trying to unit test it with PyTest (including PyTest-Mongo and PyTest-Flask). However, before I can even get to the point of writing any tests, my test script crashes. The crash happens when importing the script with my Flash app: It's trying to create the PyMongo object without a url.
My question is: How can I ensure that PyMongo is mocked correctly at this point? According to the PyTest-Mongo documentation, the MongoDB test fixture should be passed to each of the test functions, but that doesn't help me if it's crashing on import.
test_app.py:
import pytest
import pytest_mongodb
from app import app
#pytest.fixture
def client():
app.config['TESTING'] = True
return client
app.py:
import ...
app = Flask(__name__)
app.config["MONGO_DBNAME"] = os.environ.get('DB_NAME')
app.config["MONGO_URI"] = os.environ.get('MONGO_URI')
app.secret_key = os.environ.get('SECRET')
mongo = PyMongo(app)
...
if __name__ == '__main__':
app.run(host=os.environ.get('IP'),
port=int(os.environ.get('PORT')),
debug=False)
we can wrap app and mongo in a function
This works because mongo is used as a local variable.
app.py
from flask import Flask
from flask_pymongo import PyMongo
def get_app_with_config(config):
app = Flask(__name__)
app.config.from_object(config)
mongo = PyMongo(app)
#app.route("/")
def index():
pass
.
.
return app, mongo
then we can create a test file and an application execution file with different databases:
test_app.py
from app import get_app_with_config
from config import TestConfig
app, mongo = get_app_with_config(TestConfig)
run.py
from app import get_app_with_config
from config import RunConfig
app, mongo = get_app_with_config(RunConfig)
if __name__ == '__main__':
app.run(port=8000)
Sample of config.py file:
class RunConfig:
MONGO_HOST = '192.168.1.37'
MONGO_PORT = 27017
MONGO_DBNAME = 'my_database'
MONGO_URI = f"mongodb://{MONGO_HOST}:{MONGO_PORT}/{MONGO_DBNAME}"
class TestConfig:
MONGO_HOST = '192.168.1.37'
MONGO_PORT = 27017
MONGO_DBNAME = 'my_database_test'
MONGO_URI = f"mongodb://{MONGO_HOST}:{MONGO_PORT}/{MONGO_DBNAME}"
TESTING = True
Needed a quick fix so I edited app.py so that it only hard-fails if PyMongo doesn't initialise when the file is executed (i.e. it ignores PyMongo's failed initialisation when running unit-tests.)
app = Flask(__name__)
app.config["MONGO_DBNAME"] = os.environ.get('DB_NAME')
app.config["MONGO_URI"] = os.environ.get('MONGO_URI')
app.secret_key = os.environ.get('SECRET')
try:
mongodb = PyMongo(app).db
except ValueError:
"""We don't provide a URI when running unit tests, so PyMongo will fail to initialize.
This is okay because we replace it with a version for testing anyway. """
print('PyMongo not initialized!')
mongodb = None
.
.
.
if __name__ == '__main__':
if not mongodb:
print('Cannot run. PyMongo failed to initialize. Double check environment variables.')
exit(1)
app.run(host=os.environ.get('IP'),
port=int(os.environ.get('PORT')),
debug=False)
In my tests file, I just assign the mocked mongoDB client to the app in the tests that need it. Definitely not the ideal solution.
def test_redacted(client, mongodb):
app.mongodb = mongodb
...

How I can pass environment variables to my flask application

I am new to Python and writing a simple flask api which will connect to azure cosmos DB and return some response.
I want to pass db connection string as environment variable as going forward I need to dockerize this application.
So I am not sure how I can pass this connection string to my Flask application as environment variable and how to run and test my Flask application from command windows.
Below is my piece of code.
import os
from flask import Flask, request, render_template
from azure.storage.table import TableService, Entity
APP = Flask(__name__)
APP.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
connectionstring = os.environ['connectionstring']
#APP.route('/getdata')
def view_registered_guests():
print("Inside method");
table_service = TableService(connection_string=connectionstring)
table_name = 'tablebasics'
entity = table_service.get_entity(table_name, 'Harp', '2')
print(entity['email'])
print(entity['phone'])
return "Email: "+entity['email'] +" phone no: "+ entity['phone'];
if __name__ == '__main__':
APP.run(debug=True)
Any help will be appreciated.
Thanks,
Use os module
os.environ["connectionstring"]
You can set environment variables in windows cmd using SET
set connectionstring=SOMETHING
To test this i just added "connectionstring" variable and its value in system environment variables (System variables) and ran my py file and it worked.
Thanks everyone for you hints.

Categories