I am trying to integrate Flask-SocketIO with my Flask application.
For some reason I am getting an import error that is triggered by the
from app import sockets;
that I have in my admin.py and I am not sure why.
I would greatly appreciate any help provided.
admin_online/admin.py
from flask_socketio import send, emit
from flask_socketio import join_room, leave_room
from app import sockets;
#from .. import sockets//error
# from ..app import socket //also an error
from flask import Blueprint
admin_online=Blueprint('admin_online', __name__)
#sockets.on('add-message', namespace='/')
def send_disconnect(message):
print ',messae';
emit('message', message)
#sockets.on('disconnect', namespace='/')
def test_disconnect():
realoutput = "No"
print 'dscone';
#sockets.on('join', namespace='/')
def on_join(data):
username = data['username']
room = data['room']
print 'coonectg'+username;
join_room(room)
emit('message', username)
#sockets.on('leave', namespace='/')
def on_leave(data):
username = data['username']
room = data['room']
leave_room(room)
print 'leaving';
emit('message', username)
app.py
from flask import Flask
from mongo import init_mongo
from mail import init_flask_mail
from celery import Celery
from sockets import init_sockets
from admin_online import admin
def init_app():
return Flask(__name__)
app = init_app()
# Celery configuration
app.config['CELERY_BROKER_URL'] = 'redis://localhost:6379/0'
app.config['CELERY_RESULT_BACKEND'] = 'redis://localhost:6379/0'
app.config['CELERY_REDIRECT_STDOUTS_LEVEL'] = 'INFO'
def make_celery():
celery = Celery(app.import_name, backend=app.config['CELERY_RESULT_BACKEND'],
broker=app.config['CELERY_BROKER_URL'])
celery.conf.update(app.config)
TaskBase = celery.Task
class ContextTask(TaskBase):
abstract = True
def __call__(self, *args, **kwargs):
with app.app_context():
return TaskBase.__call__(self, *args, **kwargs)
celery.Task = ContextTask
return celery
with app.app_context():
init_flask_mail()
init_mongo()
sockets = init_sockets()
##imported here TOO but not worked from admin_online import admin
app.register_blueprint(admin.admin_online)
if __name__ == '__main__':
sockets.run(app, port=5000, debug=True)
socket.py
from flask import current_app as app
from flask_socketio import SocketIO
socketio = None
def init_sockets():
return SocketIO(app)
app structure
admin_online/admin.py
app.py
sockets.py
error
Traceback (most recent call last):
File "app.py", line 19, in <module>
from admin_online import admin
File "E:\Iccacerate\ICaccerate-Backend\icarcerate-backend\admin_online\admin.py", line 3, in <module>
from app import sockets;
File "E:\Ii\app.py", line 19, in <module>
from admin_online import admin
ImportError: cannot import name admin
You have circular imports. The issue is as follows:
app.py tries to import admin from admin_online.py (note that this is above the place in app.py where sockets is defined)
admin_online/admin.py tries to import sockets from app.py, which does not exist yet, because the interpreter did not complete parsing of app.py yet.
One possible solution is to move the bit of code that initializes sockets in app.py above the from admin_online import admin line.
Related
I am creating an app with python and flask. I am getting the following error:
Traceback (most recent call last):
File "C:\Users\Albert\PycharmProjects\Carro\views_trips.py", line 10, in <module>
def index():
File "C:\Users\Albert\PycharmProjects\Carro\venv\lib\site-packages\flask\scaffold.py", line 439, in decorator
self.add_url_rule(rule, endpoint, f, **options)
File "C:\Users\Albert\PycharmProjects\Carro\venv\lib\site-packages\flask\scaffold.py", line 57, in wrapper_func
return f(self, *args, **kwargs)
File "C:\Users\Albert\PycharmProjects\Carro\venv\lib\site-packages\flask\app.py", line 1090, in add_url_rule
raise AssertionError(
AssertionError: View function mapping is overwriting an existing endpoint function: index
I have only one route.
from flask import render_template, request, redirect, session, flash, url_for, send_from_directory
from app import app
from models import Trips, Users, Cars, db
import time
from helpers import *
from flask_bcrypt import check_password_hash
#app.route('/')
def index():
nickname = 'Bertimaz'
trip = Trips.query.filter_by(user_nickname=nickname).order_by(Trips.initialTime.desc()).first()
user = Users.query.filter_by(nickname='Bertimaz') # não ta achando usuario
print(user.name)
car = Cars.query.filter_by(plate=trip.car_plate)
return render_template('home.html', titulo='Viagens', trip=trip, user=user, car=car)
It was able to run it before I started implementing my SQL alchemy models and I tried changing the index function name
Instead of running the file with the routes instead of the correct script below:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_wtf.csrf import CSRFProtect
from flask_bcrypt import Bcrypt
app = Flask(__name__)
app.config.from_pyfile('config.py')
db = SQLAlchemy(app)
from views_trips import *
from views_user import *
if __name__ == '__main__':
app.run(debug=True)
In your init.py, import the Falsk app and assign the value to that app.
from flask import **app**, Flask
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
from app.config import Config
**app = Flask(__name__)
app.config.from_object(Config)**
# DB
db = SQLAlchemy(app)
migrate = Migrate(app, db)
After you have these above entries, you can import the app as
from app import app
NOTE: Do not import the app in multiple py files.
So im still learning about the structure in flask it seems flask give a too much flexibilty which is kinda confusing for me to decide, so im trying to add my Resource class to the API with the current structure
api
/__init__.py
/project.py
models
/project_management.py
configs.py
configs.json
run.py
but it return error when running
AttributeError: type object 'Project' has no attribute 'as_view'
Traceback (most recent call last):
File "e:\project-py\run.py", line 6, in
from api import * File "e:\project-py\api_init_.py", line 9, in
from .project import * File "e:\project-py\api\project.py", line 6, in
#api.add_resource(Project, '/v1/project') File "C:\Users\rokie\Anaconda3\envs\py39-rest-flask\lib\site-packages\flask_restful_init_.py",
line 391, in add_resource
self.register_view(self.app, resource, *urls, **kwargs) File "C:\Users\rokie\Anaconda3\envs\py39-rest-flask\lib\site-packages\flask_restful_init.py",
line 431, in _register_view
resource_func = self.output(resource.as_view(endpoint, *resource_class_args, AttributeError: type object 'Project' has no attribute 'as_view'
My run.py
from functools import wraps
from flask import Flask, session, g, render_template, flash
# from flask_cors import CORS, cross_origin
from flask_wtf.csrf import CSRFProtect
from pages import *
from api import *
from config import create_app
app = create_app()
app.app_context().push()
# app.register_blueprint(pages)
app.register_blueprint(api, url_prefix='/api')
# app.secret_key = "ff82b98ef8727e388ea8bff063"
csrf = CSRFProtect()
csrf.init_app(app)
if __name__ == "__main__":
app.run(host='127.0.0.1',debug=True)
Config.py
import json
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
# from flask_wtf.csrf import CSRFProtect
from flask_login import LoginManager
from flask_cors import CORS, cross_origin
db = SQLAlchemy()
ma = Marshmallow()
f = open('configs.json')
config = json.load(f)
def create_app():
app = Flask(__name__, template_folder='templates')
app.config['SQLALCHEMY_DATABASE_URI'] = config['config']['database']
app.config['SECRET_KEY'] = config['config']['secret_key']
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
api_v1_cors_config = {
"origins": ["*"]
}
CORS(app, resources={
r"/api/*": api_v1_cors_config
})
db.init_app(app)
ma.init_app(app)
login_manager = LoginManager()
login_manager.login_view = 'pages.login'
login_manager.init_app(app)
from models.user_management import User
#login_manager.user_loader
def load_user(user_id):
# since the user_id is just the primary key of our user table, use it in the query for the user
return User.query.get(int(user_id))
return app
api init.py folder with the name 'api' as the package
from flask import Blueprint
from flask_restful import Api
api_bp=Blueprint('api',__name__)
api = Api(api_bp)
# from .login import *
# from .api_project import *
from .project import *
# from .master_user import *
and lastly the project.py
from . import api
from flask import Flask, jsonify, request
from flask_restful import Resource, Api
from models.project_management import Project, ProjectStatus, Task
#api.add_resource(Project, '/v1/project')
class Project(Resource):
def get(self):
try:
print('test')
projects = Project.query.all()
return jsonify({
'message': 'Data get success',
'data': projects,
})
except Exception as e:
return jsonify({
'message': f'failed to get data {e}',
'data': []
})
enter code here
I can't check it but ...
You have the same name Project for model (Project.query.all()) and for class class Project(Resource) and this can make problem.
Because model Project is created (imported) before add_resource() so it uses this model but it has to use class Project
You may have to first define class with different name and later use add_resource() using new class
class MyProject(Resource):
# ... code ...
api.add_resource(MyProject, '/v1/project')
As the title of the question says, all the routes which are not in the main file i.e. app.py are throwing Not Found 404 error. Below are the details of my small project:
Directory structure:
server
-> user
-> __init__.py
-> models.py
-> routes.py
-> app.py
-> __init__.py
app.py:
from flask import Flask
app = Flask(__name__)
from user import routes
#app.route('/') # THIS ROUTE WORKS
def index():
return '<h1>HOME</h1>'
if __name__ == '__main__':
app.run(debug = True)
routes.py:
from app import app
#app.route('/register', methods=['GET']) # THIS DOESN'T WORK - 404 NOT FOUND ERROR
def register_user():
return '<h1>Register a user!</h1>'
I cannot find out what is wrong here, I also tried the Blueprint method but I keep getting circular import error.
EDIT:
Flask Blueprint approach:
app.py:
from flask import Flask
from pymongo import MongoClient
app = Flask(__name__)
mongo_client = MongoClient(mongoUri)
db = mongo_client[DB_NAME]
from user.routes import bp
app.register_blueprint(bp)
#app.route('/')
def index():
return '<h1>HOME</h1>'
if __name__ == '__main__':
app.run(debug = True)
user/routes.py:
from flask import Blueprint, render_template_string
from user.models import User # if I comment this, it starts working...
bp = Blueprint('user', __name__)
#bp.route('/register', methods=['POST'])
def register_user():
user = User()
user.register()
return user
#bp.route('/register', methods=['GET'])
def check_user():
return render_template_string('<h1>User Registered</h1>')
user/models.py:
import uuid
from urllib import request
from flask import jsonify
from app import db # fishy...
class User(object):
def register(self):
user = {
'_id': uuid.uuid4().hex,
'email': request.form.get('email'),
'password': request.form.get('password'),
}
db.users.insert_one(user):
return jsonify(user), 200
I'm now getting this error as I mentioned earlier:
Traceback (most recent call last):
File "D:\project\server\app.py", line 10, in <module>
from user.routes import bp
File "D:\project\server\user\routes.py", line 2, in <module>
from user.models import User
File "D:\project\server\user\models.py", line 5, in <module>
from app import db
File "D:\project\server\app.py", line 10, in <module>
from user.routes import bp
ImportError: cannot import name 'bp' from partially initialized module 'user.routes' (most likely due to a circular import) (D:\project\server\user\routes.py)
You need to first define a Blueprint, and then use that for your routes/APIs. In route.py write this:
from flask import Blueprint, render_template_string
from user.models import User
bp = Blueprint('user', __name__)
#bp.route('/register', methods=['POST'])
def register_user():
user = User()
user.register()
return user
#bp.route('/register', methods=['GET'])
def check_user():
return render_template_string('<h1>User Registered</h1>')
Then you need to import and register your blueprint. In app.py have this:
from flask import Flask
app = Flask(__name__)
from user.routes import bp
app.register_blueprint(bp)
#app.route('/')
def index():
return '<h1>HOME</h1>'
if __name__ == '__main__':
app.run(debug = True)
Have another file in the same directory as app.py, you can call it extensions.py:
from pymongo import MongoClient
mongo_client = MongoClient(mongoUri)
db = mongo_client[DB_NAME]```
And finally models.py will look like this:
...
from extensions import db
...
I have a python script which uses Flask-SqlAlchemy to access a Postgres database. However, whenever I try to query the database I receive a "working out of context" error. I figured the way to do this was to wrap it in app.app_context:
import psycopg2
import json
from simple_chalk import redBright
from ...models.bin import Bin
from ...models.station import Station
from ... import db
from datetime import datetime as dt
from ... import current_app as app
def findPositionBin(stationId, find_position):
try:
with app.app_context():
result = Bin.query.filter_by(station_id=stationId).filter_by(position=find_position).first()
print("result")
return result
except Exception as e:
print(redBright(e))
However, to do so I would need to import app. The problem is that my root init.py has the app contained in a function to be called by wsgi.py to run the program.
init.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_socketio import SocketIO
from flask_cors import CORS
import eventlet
import threading
db = SQLAlchemy()
migrate = Migrate()
socketio = SocketIO()
def create_app():
app = Flask(__name__, instance_relative_config=False)
CORS(app)
app.config.from_object('config.Config')
eventlet.monkey_patch()
socketio.init_app(app, cors_allowed_origins='*', async_mode='eventlet')
migrate.init_app(app, db)
with app.app_context():
from . import routes
from . import wsroutes
from .models import user, bin, ip_port, station
from .blueprints import user
from .blueprints.CubeStation import station_routes
from.database.CubeStation import station_database
from .server import startServer
from .blueprints.CubeStation.station_functions import broadcastLoop
# from .database.CubeStation import station_database
db.init_app(app)
app.register_blueprint(user.user_blueprint)
app.register_blueprint(station_routes.station_blueprint)
# app.register_blueprint(station_database.database_blueprint)
x = threading.Thread(target=startServer)
x.start()
t = threading.Thread(target=broadcastLoop)
t.start()
db.create_all()
return app
Would anyone happen to know how I can expose the app so it can be imported by other modules? Or if there is a better approach to this. Thanks in advance
Based here and here, maybe something in this way would work:
from init import app
def app_context():
with app.app_context():
yield
def findPositionBin(stationId, find_position, app_context):
try:
with app.app_context():
result = Bin.query.filter_by(station_id=stationId).filter_by(position=find_position).first()
print("result")
return result
except Exception as e:
print(redBright(e))
I can confirm that my unittest and api was already working but after moving my stuff to a Blueprint, my unittest kept on failing while the api is still working. I'm stumped, looking for ideas.
Here are the codes in question:
# project/app/__init__.py
from flask_sqlalchemy import SQLAlchemy
from flask import request, jsonify, abort, Flask
from instance.config import app_config
db = SQLAlchemy()
def create_app(config_name):
app = Flask(__name__, instance_relative_config=True)
app.config.from_object(app_config[config_name])
app.config.from_pyfile('config.py')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db.init_app(app)
from app.api import api
app.register_blueprint(api, url_prefix='/api')
return app
Blueprint File
# project/app/api/__init__.py
from flask import Blueprint
api = Blueprint('api', __name__)
from app.api import campaigns
Test File
# project/test_campaigns.py
import unittest
import json
from app import create_app, db
from flask import Flask, Blueprint
from instance.config import app_config
class CampaignsTestCase(unittest.TestCase):
"""Campaigns Test Case"""
def setUp(self):
"""Define test varibles and initialize app."""
self.app = create_app(config_name="testing")
self.client = self.app.test_client
self.campaigns = {'name': 'Test Campaign'}
#binds the app to the current context
with self.app.app_context():
# create all tables
db.create_all()
def test_create_campaign(self):
"""Test API can create campaign (POST Request)"""
res = self.client().post('/api/campaigns/', data=self.campaigns)
self.assertEqual(res.status_code, 201)
self.assertIn('Test', str(res.data))
### REST OF TEST ####
API Route File. This is where I used the '/campaigns' route which will be prefixed by '/api'.
# project/app/api/campaigns.py
from app.api import api
from flask_sqlalchemy import SQLAlchemy
from flask import request, jsonify, abort, Flask
import os
#api.route('/campaigns/', methods=['POST'])
def create_campaign():
if request.method == 'POST':
name = request.form['name']
if name:
campaign = Campaign(name=name)
campaign.save()
response = jsonify({
'id': campaign.id,
'name': campaign.name,
'date_created': campaign.date_created
})
response.status_code = 201
return response
All of my test results into a 404
======================================================================
FAIL: test_create_campaign (__main__.CampaignsTestCase)
Test API can create campaign (POST Request)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test_campaigns.py", line 25, in test_create_campaign
self.assertEqual(res.status_code, 201)
AssertionError: 404 != 201