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
...
Related
This is what my directory looks like
p/
student/
template/
student/
index.html/
views.py/
__init__.py/
app.py/
this is what my app.py file looks like
from flask import Flask, render_template
from p import app
#app.route("/")
def index():
return render_template("index.html")
if __name__ == "__main__":
app.run()
__init__.py file
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] =
"postgresql://postgres:1234#localhost/studentRegDB"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)
Migrate(app, db)
from p.student.views import student_blueprints
app.register_blueprint(student_blueprints, url_prefix='/student')
views.py file
from flask import Flask, request
import psycopg2
from p import db
from p.student.forms import studentform
from p.student.models import Student
from flask import Flask, render_template, url_for,redirect
from flask_blueprint import Blueprint
student_blueprints = Blueprint('student', __name__, template_folder='student')
#student_blueprints.route("/add", methods=["GET", "POST"])
def addstudent():
form = studentform()
if form.validate_on_submit():
name = request.form['name']
course = request.form['course']
new_student = Student(name,course)
db.session.add(new_student)
db.session.commit()
return redirect(url_for("success.html"))
return render_template("student.html", form=form)
when run the code i get the following error
student_blueprints = Blueprint('student', name, template_folder='student')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: Blueprint.init() got an unexpected keyword argument 'template_folder'
thank you for your help
You have to be very careful with names. The package flask_blueprint is unrelated to the flask blueprints you get from from flask import Blueprint, and has completely different parameters.
I suggest you pip uninstall flask-blueprint, and change your code to
from flask import Blueprint
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')
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
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.
My Flask application has been running fine for the last 24 hours, however I just took it offline to work on it and i'm trying to start it up again and i'm getting this error:
Traceback (most recent call last):
File "runserver.py", line 1, in <module>
from app import app
File "/home/MY NAME/APP FOLDER NAME/app.py", line 15, in <module>
from Views import *
File "/home/MY NAME/APP FOLDER NAME/Views.py", line 1, in <module>
#app.route('/contact', methods=('GET', 'POST'))
NameError: name 'app' is not defined
I am running the application currently by calling python runserver.py
runserver.py:
from app import app
app.run(threaded = True, debug=True, host='0.0.0.0')
Views.py: contains all of my routes, I won't post them all, as the error is coming from the first time app is mentioned in this file.
#app.route('/contact', methods=('GET', 'POST'))
def contact():
form = ContactForm()
if request.method == 'POST':
msg = Message("CENSORED,
sender='CENSORED',
recipients=['CENSORED'])
msg.body = """
From: %s <%s>,
%s
""" % (form.name.data, form.email.data, form.message.data)
mail.send(msg)
return "><p><br>Successfully sent message!</p></body>"
elif request.method == 'GET':
return render_template('contact.html', form=form)
app.py: Here is the top of my app.py file, where I define app = Flask(__name__) as well as import my statements.
from flask import Flask, request, render_template, redirect, url_for, send_file
from geopy.geocoders import Bing
from geopy.exc import GeocoderTimedOut
import re
import urllib
from bs4 import BeautifulSoup
from openpyxl import load_workbook
from openpyxl.styles import Style, Font
import os
import pandas as pd
import numpy as np
import datetime
from Helper_File import *
from Lists import *
from Views import *
from flask_mail import Mail, Message
from forms import ContactForm
global today
geolocator = Bing('Censored')
app = Flask(__name__)
EDIT: I have made the changes suggested in the answer below, but am getting this when I access the page:
Not Found
The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
Here is my file structure:
DHLSoftware.com
|-static
|-style.css
|-templates
|- seperate html file for each page template
|-app.py
|-forms.py
|-helper_file.py
|-Lists.py
|-runserver.py
|-Views.py
In app.py you should remove the from Views import *. Instead in your Views.py you need to have from app import app
That will bring app into the views namespace and I believe that should work for you.