Flask directory Structure - python

I have flask project which work on presently. (below)
When I run this project using command
python run.py
I get following error.
Traceback (most recent call last):
File "run.py", line 1, in
from site import app
ImportError: cannot import name 'app'
run.py
from site import app
import os
app.secret_key = os.urandom(24)
port = int(os.environ.get('PORT', 5000))
if __name__ == '__main__':
app.run(debug="True")
# app.run(host='0.0.0.0', port=port)
__init__.py
from .views import app
from .models import db
db.create_all()
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:password#localhost:5432/db'
app.config['SECURITY_REGISTERABLE'] = True
views.py
from flask import Flask
from .models import User, db
from flask import render_template, request, redirect, url_for
from flask.ext.security import login_required
app = Flask(__name__, static_url_path='')
#app.route('/')
def index():
return render_template('index.html')
#app.route('/profile/<email>')
#login_required
def user_index(email):
user = User.query.filter_by(email=email).first()
return render_template('profile.html', user=user)
#app.route('/post_user', methods=['POST'])
def post_user():
if request.form["action"] == "submit_btn":
user = User(request.form['username'], request.form['email'])
db.session.add(user)
db.session.commit()
return redirect(url_for('index'))
models.py
from flask import Flask
from flask.ext.mail import Mail, Message
from flask_sqlalchemy import SQLAlchemy
from flask.ext.security import Security, SQLAlchemyUserDatastore, UserMixin, RoleMixin
app = Flask(__name__, static_url_path='')
db = SQLAlchemy(app)
mail = Mail()
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(255), unique=True)
password = db.Column(db.String(255))
active = db.Column(db.Boolean())
confirmed_at = db.Column(db.DateTime())
roles = db.relationship('Role', secondary=roles_users,
backref=db.backref('users', lazy='dynamic'))
What should be the directory structure? Also how should I import the models and views in order to make the server work?
Please tell me if you need any other info, thanks in advance.

Rename the site's name so python dont try to import the site standard library, also is better to define the app inside the init.py file: Docs

Related

Flask/sqlalchemy | 'Blueprint' object has no attribute 'query'

I am working on a project for one of my courses at college. The project is a web application using flask and python to create the web application. I am having an issue with my project and the error I am returned is AttributeError: 'Blueprint' object has no attribute 'query' which refers to this line in my code "pagination = transaction.query.paginate(page, per_page, error_out=False)".
transaction init file
import csv
import logging
import os
from flask import Blueprint, render_template, abort, url_for,current_app
from flask_login import current_user, login_required
from jinja2 import TemplateNotFound
from app.db import db
from app.db.models import transaction
from app.transactions.forms import csv_upload
from werkzeug.utils import secure_filename, redirect
transaction = Blueprint('transaction', __name__,
template_folder='templates')
#transaction.route('/transactions', methods=['GET'], defaults={"page": 1})
#transaction.route('/transactions/<int:page>', methods=['GET'])
def transaction_browse(page):
page = page
per_page = 1000
pagination = transaction.query.paginate(page, per_page, error_out=False)
data = pagination.items
try:
return render_template('browse_transactions.html',data=data,pagination=pagination)
except TemplateNotFound:
abort(404)
app init file
"""A simple flask web app"""
import os
import flask_login
from flask import Flask
from flask_bootstrap import Bootstrap5
from flask_wtf.csrf import CSRFProtect
from flask_cors import CORS
from flask_mail import Mail
from app.auth import auth
from app.simple_pages import simple_pages
from app.cli import create_database
from app.db import database
from app.db import db
from app.db.models import User
from app.error_handlers import error_handlers
from app.logging_config import log_con, LOGGING_CONFIG
from app.context_processors import utility_text_processors
from app.transactions import transaction
mail = Mail()
login_manager = flask_login.LoginManager()
def create_app():
"""Create and configure an instance of the Flask application."""
app = Flask(__name__)
if os.environ.get("FLASK_ENV") == "production":
app.config.from_object("app.config.ProductionConfig")
elif os.environ.get("FLASK_ENV") == "development":
app.config.from_object("app.config.DevelopmentConfig")
elif os.environ.get("FLASK_ENV") == "testing":
app.config.from_object("app.config.TestingConfig")
app.mail = Mail(app)
login_manager.init_app(app)
login_manager.login_view = "auth.login"
csrf = CSRFProtect(app)
bootstrap = Bootstrap5(app)
app.register_blueprint(simple_pages)
app.register_blueprint(auth)
app.register_blueprint(database)
app.register_blueprint(log_con)
app.register_blueprint(error_handlers)
app.register_blueprint(transaction)
app.context_processor(utility_text_processors)
app.cli.add_command(create_database)
db.init_app(app)
api_v1_cors_config = {
"methods": ["OPTIONS", "GET", "POST"],
}
CORS(app, resources={"/api/*": api_v1_cors_config})
return app
#login_manager.user_loader
def user_loader(user_id):
try:
return User.query.get(int(user_id))
except:
return None
database models init file
from datetime import datetime
from sqlalchemy import Integer, ForeignKey
from sqlalchemy.orm import relationship, declarative_base
from werkzeug.security import check_password_hash, generate_password_hash
from app.db import db
from flask_login import UserMixin
from sqlalchemy_serializer import SerializerMixin
Base = declarative_base()
transaction_user = db.Table('transaction_user', db.Model.metadata,
db.Column('user_id', db.Integer, db.ForeignKey('users.id')),
db.Column('transaction_id', db.Integer, db.ForeignKey('transaction.id'))
)
class transaction(db.Model,SerializerMixin):
__tablename__ = 'transaction'
id = db.Column(db.Integer, primary_key=True)
type = db.Column(db.String(10), nullable=True, unique=False)
amount = db.Column(db.Integer)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
user = relationship("User", back_populates="transaction", uselist=False)
def __init__(self, type, amount):
self.type = type
self.amount = amount

Flask-sqlalchemy with Blueprints - RuntimeError: No application found. Either work inside a view function or push an application context

There are a lot of questions regarding this but none of them are using Flask Blueprints.
I am trying to set up a QuerySelectField with a sqlite3 lookup.
But I get then error:
RuntimeError: No application found. Either work inside a view function or push an application context.
Here is my application structure:
My init.py
from flask import Flask, render_template, current_app
from flask_mail import Mail
from flask_login import LoginManager
from flask_bootstrap import Bootstrap
from flask_ckeditor import CKEditor
from instance.config import app_config
from app.views.ticket import ticket as ticket_blueprint
from app.views.users import users as user_blueprint
from app.views.main import main as main_blueprint
from app.models import User, db
login_manager = LoginManager()
def page_not_found(e):
return render_template('404.html'), 404
def register_blueprints_on_app(app):
app.register_blueprint(user_blueprint)
app.register_blueprint(ticket_blueprint)
app.register_blueprint(main_blueprint)
def login_manager_init(app):
login_manager.login_view = 'users.login'
login_manager.init_app(app)
# associate id in the cookie with the User object
#login_manager.user_loader
def load_user(user_id):
print(user_id)
return User.query.get(user_id)
# application factory
def create_app(config):
# create application instance
app = Flask(__name__, instance_relative_config=True)
app.register_error_handler(404, page_not_found)
app.config.from_object(app_config[config])
app.config.from_pyfile('config.py')
Bootstrap(app)
mail = Mail()
mail.init_app(app)
db.init_app(app)
ckeditor = CKEditor()
ckeditor.init_app(app)
login_manager_init(app)
register_blueprints_on_app(app)
return app
And here is the problematic forms.py which is under ticket/views/
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, TextAreaField, FieldList, DateTimeField, SelectField
from wtforms_sqlalchemy.fields import QuerySelectField
from wtforms.fields.html5 import EmailField, TelField
from wtforms.validators import InputRequired, Email
from flask_ckeditor import CKEditorField
from app.models import User
def user_query():
query = User.query()
return query
class TicketForm(FlaskForm):
requested_by = QuerySelectField(label='Requested by',
query_factory=user_query(),
allow_blank=False,
get_label='fullname')
department = SelectField(label='Department')
phone = TelField(label='Phone')
email = EmailField(label='Email', validators=[Email('Enter a valid email address')])
short_desc = StringField(label='Short Description', validators=[InputRequired('Must enter a short description')])
description = CKEditorField(label='Description')
classification = StringField(label='Classification')
priority = StringField(label='Priority')
sla_respond_by = DateTimeField(label='Respond by', render_kw={'readonly': True})
sla_resolve_by = DateTimeField(label='Resolve by', render_kw={'readonly': True})
sla_status = StringField(label='SLA Status', render_kw={'readonly': True})
related_tickets = FieldList(StringField(label='Ticker #'))
client_journal = TextAreaField(label='Client Area')
work_notes = TextAreaField(label='Work Notes')
closed_at = DateTimeField(label='Closed')
closed_by = StringField(label='Closed by')
followed_by = StringField(label='Followed by')
submit = SubmitField('Save')
The problem part is when this runs
def user_query():
query = User.query()
return query
I get the error.
For context here is the routes file under ticket/view
from flask import render_template
from app.views.ticket.forms import TicketForm
from flask_login import login_required
from . import ticket
#ticket.get('/ticket')
#ticket.put('/ticket')
#login_required
def ticket():
form = TicketForm()
return render_template('ticket.html', form=form)
And in ticket/view/init.py
from flask import Blueprint
ticket = Blueprint('ticket', __name__, static_folder='static', template_folder='templates')
from . import routes
I read the doc here but it was no help. https://flask-sqlalchemy.palletsprojects.com/en/2.x/contexts/
I can't work out how to pass the application context so this function works.
I got around this by not using a query_factory in the QuerySelectfield.
I changed the field declaration from this:
class TicketForm(FlaskForm):
requested_by = QuerySelectField(label='Requested by',
query_factory=user_query(),
allow_blank=False,
get_label='full_name')
To this:
class TicketForm(FlaskForm):
requested_by = QuerySelectField(label='Requested by',
allow_blank=False,
get_label='full_name')
(so, just removed query_factory=user_query(),)
I deleted this:
def user_query():
query = User.query()
return query
Then added this to the route in my Blueprint:
#ticket.get('/ticket')
#ticket.put('/ticket')
#login_required
def ticket():
form = TicketForm()
form.requested_by.query = User.query.all() # Added this
print(current_app.app_context())
return render_template('ticket.html', form=form)
I hope that helps someone as it was doing my head in.
I'd still like to know how to do it the other way with a query_factory as I'm sure there is a way. So if anyone knows please share!

When I inherit sqlalchemy (flask app) in a class, it doesn't recognize functions such as Column()

I've been building a Flask app with the help of this video:
https://www.youtube.com/watch?v=dam0GPOAvVI&t=3256s
Here is the file of my init so far :
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from os import path
DB_NAME = "database.db"
db = SQLAlchemy()
app = Flask(__name__)
app.config['SECRET_KEY'] = 'bindthemostselling'
app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite:///{DB_NAME}'
db.init_app(app)
from views import views
from auth import auth
app.register_blueprint(views, url_prefix='/')
app.register_blueprint(auth, url_prefix='/')
if __name__ == '__main__':
app.run(debug=True)
and here is the file of my models so far its just one class:
from flask_login import UserMixin
from . import db
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(150), unique=True)
password = db.Column(db.String(150))
first_name = db.Column(db.String(150))
My problem is that the db.Column inside the User class is unrecognizable. I've tried to reinstall sqlalchemy and flask and i've looked at everything he did again and even copied the code from his github and it still wont recognize that function or even other functions that I have noticed so far from the video. This is the first time I try to make an actual python app so maybe there is something i'm missing in the syntax?
Thanks in advance.
EDIT:
So i have updated the init file to include everything so i can run and see what error i get here is what I have now:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from os import path
from models import User
from flask_login import LoginManager
DB_NAME = "database.db"
db = SQLAlchemy()
app = Flask(__name__)
app.config['SECRET_KEY'] = 'bindthemostselling'
app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite:///{DB_NAME}'
db.init_app(app)
from views import views
from auth import auth
app.register_blueprint(views, url_prefix='/')
app.register_blueprint(auth, url_prefix='/')
login_manager = LoginManager()
login_manager.login_view = 'auth.login'
login_manager.init_app(app)
#login_manager.user_loader
def load_user(id):
return User.query.get(int(id))
def create_database(app):
if not path.exists('.' + DB_NAME):
db.create_all(app=app)
print('Created Database!')
create_database(app)
if __name__ == '__main__':
app.run(debug=True)
Here is the traceback that I got (Sorry if the formatting is bad):
Traceback (most recent call last):
File "c:\Users\Ashraf\FlaskToDo_init_.py", line 4, in
from models import User
File "c:\Users\Ashraf\FlaskToDo\models.py", line 2, in
from . import db
ImportError: attempted relative import with no known parent package
so apparently the db is not imported correctly? This can't be true cause when I created the User class and passed the db.Model, it recognized it. What am I exactly missing here?
Try changing the import statement in the models file from
from . import db
to:
from init import db
This way you should get a circular import error, so move from models import User in your init after db is defined.
This is the complete setup:
init:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from os import path
from flask_login import LoginManager
DB_NAME = "database.db"
db = SQLAlchemy()
app = Flask(__name__)
app.config['SECRET_KEY'] = 'bindthemostselling'
app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite:///{DB_NAME}'
db.init_app(app)
login_manager = LoginManager()
login_manager.login_view = 'auth.login'
login_manager.init_app(app)
#login_manager.user_loader
def load_user(id):
return User.query.get(int(id))
def create_database(app):
if not path.exists('.' + DB_NAME):
db.create_all(app=app)
print('Created Database!')
create_database(app)
if __name__ == '__main__':
app.run(debug=True)
from models import User
models:
from flask_login import UserMixin
from init import db
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(150), unique=True)
password = db.Column(db.String(150))
first_name = db.Column(db.String(150))
EDIT:
add a route to actually navigate in your app:
#app.route("/")
def home():
return "Hello World"

Why do I get a NameError when importing external DB models into my Flask App?

I'm trying to split out my models into a separate file as it's getting too large to manage. I've followed this but I am getting a NameError despite having run db.create_all():
NameError: name 'importsTable' is not defined
# stack_app.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from stack_dbmodels import db
from stack_dbmodels import importsTable
from datetime import datetime
app = Flask(__name__)
app.secret_key = 'secretsquirrel'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///stack_newAppCsv.db'
db.init_app(app)
#app.route('/', methods=['GET'])
def stack():
username = "username"
new_user = importsTable(username)
db.session.add(new_user)
db.session.commit()
return "Done!"
if __name__ == "__main__":
app.run(debug = True, port=8080)
My models file:
# stack_dbmodels.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class importsTable(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80))
def __init__(self, username):
self.username = username
def __repr__(self):
return '<Import {0}>'.format(self.username)
The problem was mainly with the context of the app but during my tests there were a couple of gotchas I found. Key to make the above work was:
When I reference importsTable it wasn't initially defined unless I did:
from stack_dbmodels import db
from stack_dbmodels import importsTable
And whilst the .db file was created, the context wasn't correct so it couldn't create the actual importsTable so I added the following and problem solved, the key bit was "with app.app_context()":
db.init_app(app)
with app.app_context():
db.create_all()
Final working code was:
# stack_app.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from stack_dbmodels import db
from stack_dbmodels import importsTable
from datetime import datetime
app = Flask(__name__)
app.secret_key = 'secretsquirrel'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///stack_newAppCsv.db'
db.init_app(app)
with app.app_context():
db.create_all()
#app.route('/', methods=['GET'])
def stack():
username = "username"
new_user = importsTable(username)
db.session.add(new_user)
db.session.commit()
return "Done!"
if __name__ == "__main__":
app.run(debug = True, port=8080)

flask - NameError: name 'app' is not defined

I'm running Flask through thescript, below (run.py)
#!flask/bin/python
from app import app
app.run(debug=True)
When running the script, I have this traceback
File "./run.py", line 2, in <module>
from app import app
File "/home/andy.kwok/microblog/app/__init__.py", line 11, in <module>
lm.init_app(app)
NameError: name 'app' is not defined
I've tried to add from app import app into models.py and models.py but it does not work.
What am I doing wrong?
My __init__.py
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
import os
from flask.ext.login import LoginManager
from flask.ext.openid import OpenID
from config import basedir
lm= LoginManager()
lm.init_app(app)
oid = OpenID(app,os.path.join(basedir,'tmp'))
lm.login_view = 'login'
app = Flask(__name__)
app.config.from_object('config')
db = SQLAlchemy(app)
from app import views, models
My models.py
from app import db
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
nickname = db.Column(db.String(64), index=True, unique=True)
email = db.Column(db.String(120), index=True, unique=True)
posts = db.relationship('Post', backref='author', lazy='dynamic')
def is_authenticated(self):
return True
def is_active(self):
return True
def is_anonymous(self):
return False
def get_id(self):
try:
return unicode(self.id) # python 2
except NameError:
return str(self.id) # python 3
def __repr__(self):
return '<User %r>' % (self.nickname)
My views.py
from flask import render_template, flash, redirect, session, url_for, request, g
from flask.ext.login import login_user, logout_user, current_user, login_required
from app import app
from app import db
from app import lm
from app import oid
from .forms import LoginForm
from .models import User
#app.route('/')
#app.route('/index')
#login_required
def index():
user = g.user
posts = [
{
'author': {'nickname': 'John'},
'body': 'Beautiful day in Portland!'
},
{
'author': {'nickname': 'Susan'},
'body': 'The Avengers movie was so cool!'
}
]
return render_template('index.html',
title='Home',
user=user,
posts=posts)
#app.route('/login', methods=['GET', 'POST'])
#oid.loginhandler
def login():
if g.user is not None and g.user.is_authenticated():
return redirect(url_for('index'))
form = LoginForm()
if form.validate_on_submit():
session['remember_me'] = form.remember_me.data
return oid.try_login(form.openid.data, ask_for=['nickname', 'email'])
return render_template('login.html',
title='Sign In',
form=form,
providers=app.config['OPENID_PROVIDERS'])
#lm.user_loader
def load_user(id):
return User.query.get(int(id))
#oid.after_login
def after_login(resp):
if resp.email is None or resp.email == "":
flash('Invalid login. Please try again.')
return redirect(url_for('login'))
user = User.query.filter_by(email=resp.email).first()
if user is None:
nickname = resp.nickname
if nickname is None or nickname == "":
nickname = resp.email.split('#')[0]
user = User(nickname=nickname, email=resp.email)
db.session.add(user)
db.session.commit()
remember_me = False
if 'remember_me' in session:
remember_me = session['remember_me']
session.pop('remember_me', None)
login_user(user, remember = remember_me)
return redirect(request.args.get('next') or url_for('index'))
#app.before_request
def before_request():
g.user= current_user
You are using the app before importing it, here lm.init_app(app), app is not defined yet.
It should look like this:
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
import os
from flask.ext.login import LoginManager
from flask.ext.openid import OpenID
from config import basedir
app = Flask(__name__)
app.config.from_object('config')
lm= LoginManager()
lm.init_app(app)
oid = OpenID(app,os.path.join(basedir,'tmp'))
lm.login_view = 'login'
db = SQLAlchemy(app)
from app import views, models
This error is because of you are not defining app and directly using app
Solution is add this line in your code : app Flask(__name__)
Example: app.py
from flask import Flask
#You need to use following line [app Flask(__name__]
app = Flask(__name__)
#app.route('/')
def index():
return "Hello World with flask"
if __name__ == '__main__':
app.run(port=5000,debug=True)
This should work:
from flask import Flask
app = Flask(__name__)
#app.route("/")
def home():
return "Hello from homepage!"
if __name__ == '__main__':
app.run()

Categories

Resources