Flask models not importing propertly - python

Well, I have a Flask, SQL-Alchemy project. So far, this is my structure:
app
|__ module1
| |__ models.py
| |__ views.py
|__ module2
| |__ models.py
| |__ views.py
|__ app.py
|__ config.py
On every models.py, I have this:
from app import db
#classes
On every views.py, I have this:
from module1.models import *
from module2.models import *
from app import app
from flask import session, request, render_template, url_for, redirect
import datetime
#views
This is my app.py file:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import os
app = Flask(__name__)
db = SQLAlchemy(app)
from module1.views import *
from module2.views import *
import config
def init():
port = int(os.environ.get('PORT', 5000))
app.run(host='0.0.0.0', port=port, debug=True)
if __name__ == "__main__":
init()
When I'm on module1.views, and call a model from module2.models, works perfect. But when calling a model from module1.models on module1.views, I get a NameError:
module1.models, module1.views --> Works
module1.models, module2.views --> Works
module2.models, module1.views --> Name Error
module2.models, module2.views --> Works
Also, the import goes well, no error on that. When I call the class, it fails. I think it's some problem with the imports statements, but I don't know how to fix it. Any ideas?
Thank you guys, in advance

You might need an __init__.py file in each of the sub directories https://docs.python.org/3/tutorial/modules.html#packages.
There's more info in this answer as well that might be helpful What is __init__.py for?
Also based on the way you are sharing model functionality between views it would probably make more sense to use a directory structure like
.
├── models
│   ├── models1.py
│   └── models2.py
└── views
├── view1.py
└── view2.py

Related

Access app.logger in submodule in Flask application

I am following the official flask tutorial.
I have already set up blueprints and they are working just fine.
I can use app.logger.debug('route "/hello" called') from __init__.py to log something–my issue is that I am struggling to use the app.logger from routes/routes.py though...
I have set up a structure like this:
fzwk_access
├── __init__.py
├── db.py
├── routes
│   ├── routes.py
│   ├── ...
...
So here's the question:
how can I use the app.logger from the file routes.py?
I already tried the following:
use from flask import app which did not work
use from fzwk_access import __init__ which does not work as I don't have app as a global variable there (I guess?)
My __init__.py looks like this:
import os
from flask import Flask
def create_app(test_config=None):
# create and configure the app
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
SECRET_KEY='dev',
DATABASE=os.path.join(app.instance_path, 'flaskr.sqlite'),
)
if test_config is None:
# load the instance config, if it exists, when not testing
app.config.from_pyfile('config.py', silent=True)
else:
# load the test config if passed in
app.config.from_mapping(test_config)
# ensure the instance folder exists
try:
os.makedirs(app.instance_path)
except OSError:
pass
# a simple page that says hello
#app.route('/hello')
def hello():
app.logger.debug('route "/hello" called')
return 'Hello, World!'
from . import db
db.init_app(app)
from .routes import routes, routes_admin, routes_logs
app.register_blueprint(routes.home_bp)
app.register_blueprint(routes_admin.admin_bp)
# app.register_blueprint(routes_logs.logs_bp)
return app

Better way to implement dynamic subdomain - Flask

I'm developing a Flask application and I would like to know if exist any other way to improve the method I implemented the subdomain.
Current method:
Structure:
arquivos/
|
├── gerenciador/
| └ cadastro/
| ├── templates/
| |
| ├── __init__.py
| └── cadastro.py
|
├── __init__.py
└── views.py
file __ init __.py (arquivos/)
from flask import *
from .gerenciador.cadastro.cadastro import cadastro
app = Flask(__name__)
app.register_blueprint(cadastro, url_prefix='/cadastro', subdomain='<subdomain>')
import arquivos.views
file views.py (arquivos/)
from flask import *
from . import app
#app.route("/", subdomain="<subdomain>")
def username_index(subdomain):
pass
file __ init __.py (gerenciador/cadastro/)
from flask import *
cadastro = Blueprint('cadastro', __name__, template_folder='templates')
from . import cadastro
file cadastro.py (gerenciador/cadastro/)
from flask import *
from . import cadastro
#cadastro.route('/teste', subdomain='<subdomain>')
def cadastro_inicio(subdomain):
return 'cadastro ' + str(subdomain) + ', hello!'
This method is working, but every time I need to create a new route in gerenciador/cadastro/cadastro.py I need to repeat the "subdomain='< subdomain >'" and pass the "subdomain" to the function. Is possible to make it dynamic (without use subdomain in this file)?
Obs: If subdomain is supressed I get this error:
typeError: name_of_the_function() got an unexpected keyword argument 'subdomain'

Python fails to import packages within same folder structure

I'm creating a personal application with flask_restful, and I was doing everything with a single models.py and app.py, but the application is going to grow so I decided to make some folder restructuring.
I currently have the following structure:
/project_folder
application_name
__init__.py
controllers.py
models.py
config.py
manage.py
run.py
tests
__init__.py
test_controller.py
Everything works so far, but I want the structure to be the following:
/project_folder
application_name
__init__.py
controllers
__init__.py
brewery_controller.py
...others
models
__init__.py
base_model.py
brewery.py
...others
config.py
manage.py
run.py
tests
__init__.py
test_controller.py
But I can't seem to make it work. Here is the application __init__.py
#/project_folder/application_name/__init__.py
import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_restful import Api
from controllers import BreweryList, BreweryResource
from models import db
def initApp(config):
app = Flask(__name__)
app.config.from_object(config)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db.init_app(app)
api = Api(app)
api.add_resource(BreweryList, '/breweries')
api.add_resource(BreweryResource, '/breweries/<brewery_id>')
return app
I tried with
from brewery_controller import BreweryList, BreweryResource
from base_model import db
with no luck. I keep getting ImportError: cannot import BreweryList and the same goes for db if I uncomment the Brewery classes import line.
The controllers/__init__.py and models/__init__.py are both empty.
Here is also the run.py
import os
from beerinv import initApp
if __name__ == '__main__':
app = initApp(os.environ['APP_SETTINGS'])
app.run()
Could solve the issue by following #davidism comment by putting full import path:
from application_name.controllers.brewery_controller import BreweryList, BreweryResource
from application_name.models.base_model import db

Flask: App structure to avoid circular imports

I am following the book Mastering flask's recommended file structure.
(The name of my project is Paw)
In Paw/paw/__init__.py:
def create_app(object_name):
app = Flask(__name__)
app.config.from_object(object_name)
db.init_app(app)
robot = LoggingWeRobot(token='banana', enable_session=True)
robot.init_app(app, endpoint='werobot', rule='/wechat')
attach_debugging_logger(app)
app.register_blueprint(poll_blueprint)
app.register_blueprint(wechat_blueprint)
return app
Note that the robot variable is actually needed in my blueprint, wechat, found in: Paw/paw/controllers/wechat.py
#robot.handler
def request_logging_middleware(message, session):
app.logger.debug("\n%s", request.data)
return False # This allows other handlers to continue execution
So my problem is that my blueprint has no access to the robot variable. However, the robot variable should be created in create_app in Paw/paw/__init__.py because I am trying to follow the application factory pattern.
Any recommendation on how to fix this? My project can be found here and I am trying to follow this application structure
Simply use the same pattern you are using for db - create robot elsewhere and import it into your Paw/paw/__init__.py file, just as you do with db:
import db from models
import robot from wechat_setup
# wechat_setup is where you would invoke
# robot = LoggingWeRobot(token='banana', enable_session=True)
def create_app(object_name):
app = Flask(__name__)
app.config.from_object(object_name)
db.init_app(app)
robot.init_app(app, endpoint='werobot', rule='/wechat')
I usually put project global variables in one file (say gvars.py).
Then the project structure will be some sort like this:
.
├── etc
│   └── webapp.py
├── models
│   └── common.py
├── views
│   └── common.py
├── gvars.py
└── webapp.py
In other files we just do this:
from gvars import db, robot # or other variables

Bottle app does not process routes put into a separate module within a package

I have this directory structure:
.
├── controller
│   ├── FooController.py
│   ├── __init__.py
│
├── main.py
FooController:
from bottle import get, post, request, response, run, abort, \
redirect, LocalResponse
import json
#get('/')
def create():
response.content_type = 'application/json'
return json.dumps({'hello2' : 'world'})
I execute python main.py which has:
from controller import *
from bottle import get, post, request, response, run, abort, \
redirect, LocalResponse
if __name__ == '__main__':
run(host = 'localhost', port = 8080)
I was hoping that that by importing all controllers (in this case FooController), it would hook into the framework. But it doesn't when I go to localhost:8080/ I get a 404 error. If I put all my routes into main.py, it works.
Does anyone know how I can accomplish what I'm looking for?
Not sure this is the best way to modularize your app, but
from controller.FooController import *
is the proper way to do the import, and it'll fix your 404 error.

Categories

Resources