flask - blueprint - sqlalchemy - cannot import name 'db' into moles file - python

I'm new in bluprint, and have problem with importing db into mydatabase.py file which is models file.
I've faced with this error:
ImportError: cannot import name 'db'
The tree of my project
nikoofar/
run.py
bookshelf/
__init__.py
mydatabase.py
main/
controllers.py
__init__.py
run.py
from bookshelf import app
if __name__ == '__main__':
app.run(debug=True, port=8000)
bookshelf / intit.py
from flask import Flask
from bookshelf.main.controllers import main
from flask_sqlalchemy import SQLAlchemy
from mydatabase import pmenu
app = Flask(__name__, instance_relative_config=True)
db = SQLAlchemy(app)
db.init_app(app)
application.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://username:password#localhost/databasename'
app.config.from_object('config')
app.register_blueprint(main, url_prefix='/')
bookshelf / main / controllers.py
from flask import Blueprint
from bookshelf.mydatabase import *
from flask_sqlalchemy import SQLAlchemy
main = Blueprint('main', __name__)
#main.route('/')
def index():
g = pmenu.query.all()
print (g)
return "ok"
The problem backs to from bookshelf import db, and if I delete that, the error will be changed to:
ImportError: cannot import name 'db'
bookshelf / mydatabase.py
from bookshelf import db
class pmenu(db.Model):
__tablename__ = 'p_menu'
id = db.Column(db.Integer, primary_key=True)
txt = db.Column(db.String(80), unique=True)
link = db.Column(db.String(1024))
def __init__(self, txt, link):
self.txt = txt
self.link = link
def __repr__(self):
return "{'txt': " + self.txt + ", 'link':" + self.link + "}"
Any solution?

This is actually a simple, yet frustrating issue. The problem is you are importing main BEFORE you are creating the instance of db in your __init__.py
If move the import to after your db = SQLAlchemy(app), it will work:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://uername:password#localhost/test'
db = SQLAlchemy(app)
from bookshelf.main.controllers import main #<--move this here
app.register_blueprint(main, url_prefix='/')

Related

NameError: name 'app' is not defined In Python

I am new to flask and i have been struggling to create an sqlite database but whenever i run the from app import db I get the error message:
NameError: name 'app' is not defined
This is my code:
from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
app = Flask(__name__)
db = SQLAlchemy()
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
db.init_app(app)
class Todo:
id = db.Column(db.Integer(), primary_key=True)
content = db.Column(db.String(length=300), nullable=False)
date_created = db.Column(db.DateTime, default=datetime.utcnow)
def __repr__(self):
return '<Task %r>' % self.id
#app.route('/')
def index():
return render_template('index.html')
if __name__ == "__main__":
app.run(debug=True)`
The image below is my directory structure. I don't know if it has anything to do with it: Image of directory structure
I tried import db from app so that I will create the db file.
First u need to replace db.init_app(app) with db = SQLAlchemy(app). The starting code could look like this:
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
db = SQLAlchemy(app)
Then after your class Todo:
with app.app_context():
db.create_all()

ImportError: cannot import name 'app' from partially initialized module 'market' (most likely due to a circular import)

I was trying to package my code as it was getting kind of complex for me to keep in one file and i encountered an import error when i tried to run the file that says circular import error, how do i solve this error? I have been analyzing the code and i cannot seem to be able to figure out what might be wrong.
run.py
from market import app
if __name__ == "__main__":
app.run(debug=True)
init.py
from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy
from market import routes
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///market.db"
db = SQLAlchemy(app)
routes.py
from market import app
from flask import render_template
from market.models import Item
#app.route("/")
#app.route("/home")
def home():
return render_template("index.html")
#app.route("/market")
def market():
items = Item.query.all()
return render_template("market.html", items=items)
models.py
from market import db
class Item(db.Model):
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(length=30), nullable=False, unique=True)
price = db.Column(db.Integer(), nullable=False)
barcode = db.Column(db.String(length=12), nullable=False, unique=True)
description = db.Column(db.String(length=1024), nullable=False, unique=True)
def __repr__(self):
return f"Item {self.name}"
project structure
error
Moving your routes import to the bottom of the file should help.
Just as you would do for example with blueprints in application factory. You import blueprints/views after you create app instance with app = Flask(__name__):
def create_app(config_filename):
app = Flask(__name__)
app.config.from_pyfile(config_filename)
from yourapplication.model import db
db.init_app(app)
from yourapplication.views.admin import admin
from yourapplication.views.frontend import frontend
app.register_blueprint(admin)
app.register_blueprint(frontend)
return app
Also check:
Is a Python module import at the bottom ok?
in your __init__.py you import routes
in routes.py you import app (defined in __init__.py)

SQLite database not updating after submiting form from flask-wtforms

These are my different files, not all though. Everything works fine until the part where I submit a form. I suspect it has something to do with the linking of the database if that makes sense?
#init.py
import os
from os import path
from venv import create
from flask import Flask, render_template, flash, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
from auth import auth
from models import db
from main import app
basedir = os.path.abspath(os.path.dirname(__file__))
DB_NAME = "bookings.sqlite"
app.config\['SECRET_KEY'\] = 'Thisissupposedtobesecret!'
app.config\['SQLALCHEMY_DATABASE_URI'\] = 'sqlite:///' + os.path.join(basedir, DB_NAME)
app.config\['SQLALCHEMY_TRACK_MODIFICATIONS'\] = False
app.register_blueprint(auth, url_prefix="/")
db.init_app(app)
def create_database(app):
if not path.exists('V3/' + DB_NAME ):
db.create_all(app=app)
create_database(app)
if __name__ == '__main__':
app.run(debug=True)
#forms.py
from flask_wtf import FlaskForm
from wtforms import (StringField, BooleanField, DateTimeField,
RadioField,SelectField,
TextAreaField,SubmitField)
from wtforms.validators import DataRequired
class SignUpForm(FlaskForm):
name = StringField("Your FULL Name", validators=\[DataRequired()\])
(form questions)
submit = SubmitField("Book")
#models.py
from main import app
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
db = SQLAlchemy(app)
Migrate(app,db)
class Booking(db.Model):
__tablename__ = "bookings"
id = db.Column(db.Integer,primary_key=True)
name = db.Column(db.Text)
(other colums)
def __init__(self,name):
self.name = name
Tried to submit form which was successful but was not updated in the database
You need to push a context so you can access the database
https://flask.palletsprojects.com/en/2.0.x/appcontext/
def create_database(app):
if not path.exists('V3/' + DB_NAME ):
with app.app_context():
db.create_all()
Under models.py added
def __init__(self,name,x,y,z):
self.name = name
self.x = x
self.y = y
self.z = z
Under auth.py added
if request.method == 'POST':
name = form.name.data
x = form.x.data
y = form.y.data
z = form.z.data
new_booking = Booking(name=name,x=x,y=y,z=z)
db.session.add(new_booking)
db.session.commit()
return redirect(url_for('auth.bookings'))
else:
return render_template('bookings.html', form=form)
this has solved the issue, although i do not exactly understand why but it solved it

Flask-testing database not saving on commit

I have the following flask factory directory setup:
server/
__init__.py
.env
wsgi.py
app/
__init__.py
config/
__init__.py
config.py
test_config.py
models/
__init__.py
sku.py
views/
__init__.py
sku_bp.py
tests/
__init__.py
test_sku_view.py
The create_app method is defined in server/app/__init__.py:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def create_app(config):
app = Flask(__name__, instance_relative_config=False)
app.config.from_object(config)
db.init_app(app)
with app.app_context()
from app.views.sku_bp import sku_bp
app.register_blueprint(sku_bp, url_prefix='/api/sku/')
return app
And the model (server/app/models/sku.py) and blueprint (server/app/views/sku_bp.py) are given by:
from app import db
class SKU(db.Model):
__tablename__ = 'sku'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False)
def to_dict(self):
return {'id': self.id, 'name': self.name}
and
from flask import Blueprint, jsonify
from app.models.sku import SKU
sku_bp = Blueprint('sku_bp', __name__)
#sku_bp.route('/get/')
#sku_bp.route('/get/<string:sku_name>')
def get(sku_name: str):
try:
sku = SKU.query.filter_by(name=sku_name).first()
except Exception as e:
return jsonify({'Error': f'{e}'}), 404
else:
return jsonify(sku.to_dict()), 200
respectively.
I am trying to the compute unit tests in server/tests/test_sku_view.py as follows:
import unittest
import sys
sys.path.append('./')
from flask_testing import TestCase
import pandas as pd
from app.models.sku import SKU
from app.config.test_config import TestConfig
from app import create_app, db
class TestSKUView(TestConfig, TestCase):
def create_app(self):
return create_app(TestConfig)
def setUp(self):
db.create_all()
df_sku = pd.read_csv('tests/io/test.sku.csv')
for index, row in df_sku.iterrows():
sku = SKU(**row)
db.session.commit()
def tearDown(self):
db.session.remove()
db.drop_all()
def test_sku_view(self):
skus = SKU.query.all()
print(f'skus = {skus}')
def main():
unittest.main()
if __name__ == '__main__':
main()
where the server/tests/io/test.sku.csv file looks like this:
id,name
1,'A'
2,'B'
and the server/app/config/test_config.py file looks like this:
class TestConfig():
DEBUG = True
TESTING = True
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_ECHO = True
SQLALCHEMY_DATABASE_URI = 'sqlite:////tmp/test.db'
I call this script from within the server/ directory using python3.7 tests/test_sku_view.py. However, when I print the skus list which queries the database, nothing is returned, i.e. skus = []. Where am I going wrong here, please? I know the sku is being generated properly but it seems not to save in the database on commit ...
You need to add a db.session.add(sku) before the commit, obviously in the for loop :-)

How to fix 'flask db.create_all() error'?

I'm have flask init with create app function. I create test file for my unitests. In unitest class add setUp function were i create new flask app and add context, push context to it. Next i create test db with create_all() function and, where i start test file, i have next error:
in _execute_for_all_tables op(bind=self.get_engine(app, bind), **extra)
TypeError: create_all() got an unexpected keyword argument 'forms'
I haven't 'forms' files or variable on models or anywere.
Before this error place in flask_sqlalchemy/init.py MetaData(bind=None), may be it some help.
from flask import Flask
from config import Config
from blocker_application.database import db
from flask_migrate import Migrate
from flask_login import LoginManager
from flask_moment import Moment
migrate = Migrate()
login = LoginManager()
login.login_view = 'user.login'
moment = Moment()
def create_app(config_class=Config):
app = Flask(__name__)
app.config.from_object(config_class)
db.init_app(app)
migrate.init_app(app, db)
login.init_app(app)
moment.init_app(app)
from blocker_application.main.routes import bp_main
from blocker_application.errors.handlers import bp_error
from blocker_application.reports.routes import bp_reports
from blocker_application.user.routes import bp_user
from blocker_application.applications.routes import bp_applications
app.register_blueprint(bp_main)
app.register_blueprint(bp_error)
app.register_blueprint(bp_reports, url_prefix='/reports')
app.register_blueprint(bp_user, url_prefix='/user')
app.register_blueprint(bp_applications, url_prefix='/applications')
return app
from blocker_application import models
________________________________________________________________________
/config.py
import os
basedir = os.path.abspath(os.path.dirname(__file__))
class Config:
SECRET_KEY = os.environ.get('SECRET_KEY') or 'not realy finish secret key configuration'
SQLALCHEMY_DATABASE_URI = 'mysql://some_database'
SQLALCHEMY_TRACK_MODIFICATIONS = False
class TestConfig(Config):
TESTING = True
SQLALCHEMY_BINDS = {'test': 'mysql://some_database_test'}
______________________________________________________________________
/tests.py
import unittest
from blocker_application import create_app, db
from blocker_application import models
from config import TestConfig
class UserModelCase(unittest.TestCase):
def setUp(self):
self.app = create_app(TestConfig)
self.app_context = self.app.app_context()
self.app_context.push()
db.create_all(bind='test')
def tearDown(self):
db.session.remove()
db.drop_all(bind='test')
self.app_context.pop()
def test_password(self):
u = models.User(username='Mark')
u.set_password('Mark')
self.assertTrue(u.check_password('Mark'))
self.assertFalse(u.check_password('Tony'))
if __name__ == '__main__':
unittest.main(verbosity=2)
I found decision. Unittest work ok, after recreate the virtual enveroment.

Categories