Import reflected Flask-SQLAlchemy Module before creating the app - sqlalchemy

This is a continuation of this question.
As my flask app should not write anything in my database, I set up Flask-SQLAlchemy to reflect my database. This way I do not have to change my models, when I change my schema:
# app/__init__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
db.init_app(app)
with app.app_context():
db.Model.metadata.reflect(db.engine)
# app/models.py
from app import db
class Data(db.Model):
__table__ = db.Model.metadata.tables['data']
But now, if I have to import the Model before I created the app, I run into Errors because the metadata is not set yet. This is a problem when it comes to testing for example:
# test.py
import unittest
from app import create_app, db
from app.models import Data
class TestGUI(unittest.TestCase):
#classmethod
def setUpClass(cls):
cls.app = create_app()
# etc ...
This throws KeyError: 'data' in __table__ = db.Model.metadata.tables['data'] when importing from app.models as the metadata is not correctly set before the create_app() function is run.

I did find a solution (thanks to #snakecharmerb). The solution is simply to avoid the problem, to not import app.models before running create_app(). A bit hacky, so feel free to post an answer as well, when you have a better solution.
My test file now looks like this:
# test.py
import unittest
from app import create_app, db
app = create_app()
from app.models import Data
class TestGUI(unittest.TestCase):
#classmethod
def setUpClass(cls):
cls.app = app
# etc ...

Related

Same dash dashboard template with different dataset inside a flask app. How to do it?

I'm looking for the simplest way to generate the same dash dashboard X times with different dataset.
Each dashboard is a single page and the main app is a flask app.
The goal is to have a dashboard template running on different dash instance with different dataset.
I started with the following code, but I'm struggling when dash pages include callbacks i.e when html.Div([html.H1('Hi there, I am app1 for reports')]) turns into a bigger function with callback
import dash
import dash_html_components as html
from flask import Flask, render_template, redirect
from werkzeug.middleware.dispatcher import DispatcherMiddleware
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello from Flask!'
#app.route('/test2')
def t2():
return render_template('test2.html')
dash_app1 = dash.Dash(__name__, server = app, url_base_pathname='/dashboard/' )
dash_app2 = dash.Dash(__name__, server = app, url_base_pathname='/reports/')
dash_app1.layout = html.Div([html.H1('Hi there, I am app1 for reports')])
dash_app2.layout = html.Div([html.H1('Hi there, I am app2 for reports')])
#app.route('/dashboard')
def render_dashboard():
return redirect('/dash1')
#app.route('/reports')
def render_reports():
return redirect('/dash2')
app = DispatcherMiddleware(app, {
'/dash1': dash_app1.server,
'/dash2': dash_app2.server
})
So my question is what is the best way/architecture to manage muti dash dashboards, based on the same template, running different data ?
In case it might help, I found a solution encapsulating the layout, callbacks and return function into a class.
flask_app.py
from flask import Flask, render_template, redirect
import dash
from apps.dashboard1 import Dashboard1
from apps.dashboard2 import Dashboard2
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello from Flask!'
#app.route('/test')
def test():
return render_template('test.html')
dash_app1 = dash.Dash(__name__, server = app, url_base_pathname='/dashboard1/' )
dash_app1.config.suppress_callback_exceptions = True
dash_app1.layout = Dashboard1(dash_app1).layout
#app.route('/dashboard1')
def render_dashboard():
return redirect('/dash1')
dash_app2 = dash.Dash(__name__, server = app, url_base_pathname='/dashboard2/')
dash_app2.config.suppress_callback_exceptions = True
dash_app2.layout = Dashboard2(dash_app2).layout
#app.route('/dashboard2')
def render_dashboard2():
return redirect('/dash2')
if __name__ == '__main__':
app.run(debug=True)
apps/dashboard1.py
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
class Dashboard1:
def __init__(self, app_dependency):
self.app_dependency = app_dependency
html.P("Your code here"),
dcc.Dropdown(...),
...
dcc.Graph(id="pie-chart"),
])
#self.app_dependency.callback(
Output("pie-chart", "figure"),
Input('organisations', 'value'))
def update_output_div(selected_org):
your_update_function
return your_outputs

Save data type JSONField from celery

model.py:
from django.db import models
from datetime import datetime
from django.db.models import TextField, JSONField, Model
# Create your models here.
class reservation(models.Model):
res=models.JSONField()
da = models.DateTimeField(default=datetime.now, blank=True)
tasks.py:
#shared_task
def ress():
content={
"customer": 48,
"reservation_id_pms": str(id),
"reservation_channel_number": None,
"reservation_group_id_pms": "ed2b9d55-46d9-4471-a1e9-ad6c00e30661",
"extra_reservation_code": "550ca1c1",
}
reservations=reservation.objects.create(res=content)
reservations.save()
res.append(content)
return None
error:
from django.db.models import TextField, JSONField, Model ImportError:
cannot import name 'JSONField' from 'django.db.models'
(/usr/lib/python3/dist-packages/django/db/models/init.py)
It is possible that you are using lower versions of Django (< 1.9) when JSONField was not introduced. So try upgrading the version.
If this is not the case, then try installing simplejson library as sometimes the library may not come with Django itself.
pip install simplejson

Multiprocessing, sqlAlchemy and scoped_sessions

I want to run multiple strategies in concurrent processes. I came up with something like this
import logging
import multiprocessing
import os
from sqlalchemy.orm import scoped_session, Session
from pyutil.sql.interfaces.symbols.symbol import Symbol
from pyutil.sql.session import get_one_or_create
class StratRunner(object):
def __init__(self, session_scope, logger=None):
assert isinstance(session_scope, scoped_session)
self.__session_scope = session_scope
self.__logger = logger or logging.getLogger(__name__)
# this function is the target for mp.Process
def _run(self, strategy):
self.__logger.debug("Pid {pid}".format(pid=os.getpid()))
symbols = self.symbols
self.__logger.info("Run strategy {s}".format(s=strategy))
configuration = strategy.configuration()
strategy.upsert(portfolio=configuration.portfolio, symbols=symbols, days=5)
def run_strategies(self):
# loop over all active strategies!
jobs = []
# we are in the main thread here...
for s in self.active_strategies:
# what shall I give to the Process? The strategy object, the strategy_id, a session instance, the session_scope...
job = multiprocessing.Process(target=self._run, kwargs={"strategy": s})
job.name = s.name
jobs.append(job)
run_jobs(jobs, logger=self.__logger)
#property
def symbols(self):
return {s.name: s for s in self.__session_scope().query(Symbol)}
#property
def active_strategies(self):
return self.__session_scope().query(Strategy).filter(Strategy.active == True).all()
I am aware of tons of documentation on this project but I am overwhelmed.
I loop over the rows of a table (The active_strategies). class Strategies(Base)... . I then hand over the strategy object to the _run method and update the strategy object within the very same method. Please feel free to shred my code.
I am in particular puzzled about what to give to the _run method? Shall I hand over the strategy object, the strategy ID, the session, the scoped_session, ... ?
I have now created a runner object:
import abc
import logging
import os
from sqlalchemy.orm import sessionmaker
class Runner(object):
__metaclass__ = abc.ABCMeta
def __init__(self, engine, logger=None):
self.__engine = engine
self._logger = logger or logging.getLogger(__name__)
self.__jobs = []
#property
def _session(self):
""" Create a fresh new session... """
self.__engine.dispose()
factory = sessionmaker(self.__engine)
return factory()
def _run_jobs(self):
self._logger.debug("PID main {pid}".format(pid=os.getpid()))
for job in self.jobs:
# all jobs get the trigge
self._logger.info("Job {j}".format(j=job.name))
job.start()
for job in self.jobs:
self._logger.info("Wait for job {j}".format(j=job.name))
job.join()
self._logger.info("Job {j} done".format(j=job.name))
#property
def jobs(self):
return self.__jobs
#abc.abstractmethod
def run(self):
""" Described in the child class """
In particular this class can provide a fresh session (via ._session). However, using this setup I see plenty of :
psycopg2.OperationalError: server closed the connection unexpectedly
| This probably means the server terminated abnormally
| before or while processing the request.

HTMLTestRunner is not working

I'm trying to generate an HTML report from my Unittests of Python3.6. I'm using the HTMLTestRunner library.
Here are my unit tests:
#!/usr/bin/env python
import unittest
import boto3
import warnings
import HTMLTestRunner
class SecurityGroupTest(unittest.TestCase):
def setUp(self):
session = boto3.Session(profile_name='default')
self.ec2_clt = session.client('ec2')
def test_delete_03(self):
response = self.ec2_clt.describe_security_groups()
self.assertEqual(len(response['SecurityGroups']), 0)
if __name__ == "__main__":
HTMLTestRunner.main()
When I run the tests, nothing is generated. What am I missing here?

connect to MySQL data base with QSqlDatabase pyqt4

im new to python code, QT and MySQL, i wanna show a data base in a QtableView but i cant it.
i dont know whats happend, the error is ('QSqlDatabase' object has no attribute 'setHotsName')
the code is:
# -*- coding: utf-8 -*-
import sys
import mysql.connector
from PyQt4 import QtSql, QtCore, QtGui, uic
form_class = uic.loadUiType("dialog.ui")[0]
def crearConexion():
db = QtSql.QSqlDatabase.addDatabase('QMYSQL')
db.setHotsName('localhots')
db.setDatabaseName('Registro')
db.setUserName('root')
db.setPassword('xxxx')
db.open()
print(db.lastError().text())
return True
class MiClase(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setupUi(self)
self.model=QtSql.QSqlTableModel(self)
self.model.setTable("RegistroIN")
self.model.setEditStrategy(QtSql.QSqlTableModel.OnManualSubmit)
self.model.select()
self.tableView.setModel(self.model)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
if not crearConexion():
sys.exit(1)
MiApp = MiClase()
MiApp.show()
sys.exit(app.exec_())
somebody that help me? thank you.