Ok so I am new to flask and i am trying to set up a simple task manager. And I have a problem with importing my database.
When I made my first import my db was named User and it had fields like email, username, ...
Now all I did was renaming the call of database form User to Task and changed some fields or added more.
and now when I run a command:
>>> from app.models import Task
I get an error:
Traceback (most recent call last):
File "<input>", line 1, in <module>
ImportError: cannot import name 'Task' from 'app.models' (/Users/janzaplatil/Desktop/taskmanager/app/models.py)
but if I run a >>> from app.models import User all is fine. But it makes no sense to me since there is no class User, only Task
My model python file:
from datetime import datetime
from app import db
class Task(db.Model):
id = db.Column(db.Integer, primary_key=True)
task = db.Column(db.String(64), index=True, unique=True)
description = db.Column(db.String(120), index=True, unique=True)
start = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
password_hash = db.Column(db.String(128))
def __repr__(self):
return '<Task {}>'.format(self.task)
My flask app:
from app import app, db
from app.models import Task
#app.shell_context_processor
def make_shell_context():
return {'db': db, 'Task': Task}
Related
I'm writing a site for a Flask,and I made a mistake when I want to connect migrations, shows this error
sqlalchemy.exc.NoForeignKeysError: Could not determine join condition between parent/child tables on relationship Users.roles - there are no foreign keys
linking these tables via secondary table 'сайт.role_users'. Ensure that referencing columns are associated with a ForeignKey or ForeignKeyConstraint, or
specify 'primaryjoin' and 'secondaryjoin' expressions.
Here is my code:
from flask import Flask, render_template, request, flash, \
redirect, url_for
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
from flask_admin import Admin
from flask_admin.contrib.sqla import ModelView
from flask_migrate import Migrate
from flask_security import RoleMixin
import os
css_file = 'static/css/main.css'
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///lib.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SECRET_KEY'] = os.getenv('SECRET_KEY')
db = SQLAlchemy(app)
manager = LoginManager(app)
migrate = Migrate(app, db)
role_users = db.Table('role_users',
db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
db.Column('role_id', db.Integer(), db.ForeignKey('role.id')),
)
class Users(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
login = db.Column(db.String(75), nullable=False, unique=True)
password = db.Column(db.String(80), nullable=False)
roles = db.relationship('Roles', secondary=role_users, backref=db.backref('users',
lazy='dynamic'))
def __repr__(self):
return f'<User> -----> {self.login}'
class Roles(db.Model, RoleMixin):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), unique=True, nullable=False)
def __repr__(self):
return f'<Role> ----> {self.title}'
Although there were no such errors during the first migration
.......
Help solve this problem
I'm new to flask, and have problem with importing db while running from python console/cmd.
I'm facing this error :
In[67]: os.getcwd()
Out[67]: 'C:\\Users\\Desktop\\Python\\Flask'
In[68]: os.listdir()
Out[68]:
['app',
'app.db',
'config.py',
'Flask.py',
'migrations',
'venv',
'__init__.py',
'__pycache__']
In[69]: from Flask.app.models import User,Post
Traceback (most recent call last):
File "C:\Users\AppData\Local\Continuum\anaconda3\lib\site-packages\IPython\core\interactiveshell.py", line 3326, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-69-dca3714f084d>", line 1, in <module>
from Flask.app.models import User,Post
File "C:\Program Files\JetBrains\PyCharm Community Edition 2019.3\plugins\python-ce\helpers\pydev\_pydev_bundle\pydev_import_hook.py", line 21, in do_import
module = self._system_import(name, *args, **kwargs)
File "C:\Users\Desktop\Python\Flask\app\models.py", line 1, in <module>
from Flask.app import db
ImportError: cannot import name 'db' from 'Flask.app' (C:\Users\Desktop\Python\Flask\app\__init__.py)
The tree of my project :
Flask/
app/
__init__.py
forms.py
models.py
routes.py
__init__.py
config.py
Flask.py
Flask/init.py
app/init.py
from flask import Flask
from Flask.config import Config
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
migrate = Migrate(app, db)
from Flask.app import routes, models
app/models.py
from Flask.app import db
from datetime import datetime
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), index=True, unique=True)
email = db.Column(db.String(120), index=True, unique=True)
password_hash = db.Column(db.String(128))
def __repr__(self):
return '<User {}>'.format(self.username)
When running flask run via command it's working fine. But I when I'm trying to run via python console or cmd I'm not able to run successfully.
Thanks
there is a problem when importing module fix this....
inside Flask remove the __init_.py here u didnt want a init file.if the Flask folder is the root folder others are sub folders inside it I guess your main file is Flask.py. So
change the
from Flask.app import db
to
from app import db
considering db is declared inside app/init.py
I'm making migrations in Flask using unsurprisingly Flask-Migrate.
once I execute python manage.py db init it creates directory migrations with initial migrations file. Then
I execute python manage.py db migrate and I get this:
...
...
target_metadata = current_app.extensions['migrate'].db.metadata
AttributeError: 'NoneType' object has no attribute 'metadata'
I understand from this output that 'migrate' is None hence I'm getting an attribute error.
models.py:
from sqlalchemy.sql import func
from project import db, bcrypt
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(128), nullable=False, unique=True)
email = db.Column(db.String(128), nullable=False, unique=True)
password = db.Column(db.String(255), nullable=False)
active = db.Column(db.Boolean(), default=True, nullable=False)
created_date = db.Column(db.DateTime, default=func.now(), nullable=False)
def __init__(self, username, email, password):
self.username = username
self.email = email
self.password = bcrypt.generate_password_hash(password).decode()
def to_json(self):
return {
'id': self.id,
'username': self.username,
'email': self.email,
'active': self.active,
}
The question is why nothing is being passed to it ? I'm following a tutorial and I'm not supposed to have this error.
I've got this from similar topic:
NoneType means that instead of an instance of whatever Class or Object
you think you're working with, you've actually got None. That usually
means that an assignment or function call up above failed or returned
an unexpected result.
this is what I've found in env.py file in the migrations directory:
from flask import current_app
config.set_main_option('sqlalchemy.url',
current_app.config.get('SQLALCHEMY_DATABASE_URI'))
target_metadata = current_app.extensions['migrate'].db.metadata
current_app is being imported from Flask but doesn't contain the extension migrate from which I need to use the metadata.
There's no reason for it to be throwing None though because the extension is correctly initilised in __init__.py file:
...
...
from flask_migrate import Migrate
db = SQLAlchemy()
toolbar = DebugToolbarExtension()
cors = CORS()
migrate = Migrate()
bcrypt = Bcrypt()
def create_app(script_info=None):
app = Flask(__name__)
app_settings = os.getenv('APP_SETTINGS')
app.config.from_object(app_settings)
app.config.from_object('project.config.DevelopmentConfig')
toolbar.init_app(app)
cors.init_app(app)
db.init_app(app)
migrate.init_app(app) # <--
bcrypt.init_app(app)
from project.api.users import users_blueprint
app.register_blueprint(users_blueprint)
#app.shell_context_processor
def ctx():
return {'app': app, 'db': db}
return app
I had a missing argument in the initialization of the migrate extension. Migrate takes in the app instance and the instance of db.
def create_app(script_info=None):
app = Flask(__name__)
app_settings = os.getenv('APP_SETTINGS')
app.config.from_object(app_settings)
app.config.from_object('project.config.DevelopmentConfig')
toolbar.init_app(app)
cors.init_app(app)
db.init_app(app)
migrate.init_app(app, db) # <--
bcrypt.init_app(app)
from project.api.users import users_blueprint
app.register_blueprint(users_blueprint)
#app.shell_context_processor
def ctx():
return {'app': app, 'db': db}
return app
I am trying to use the Python Terminal to add a user using the following commands:
from app import db
from app.models import User, Post
u = User(username='Jordan',email='jtest#test.net')
db.session.add(u)
db.session.commit()
Below is my model:
class User(db.Model):
id = db.Column(db.Integer, db.Sequence('id_seq'), primary_key=True)
username = db.Column(db.String(64), unique=True)
email = db.Column(db.String(120), unique=True)
password = db.Column(db.String(128))
posts = db.relationship('Post', backref='author',lazy='dynamic')
def __repr__(self):
return 'User {}'.format(self.username)
Init script:
from flask import Flask
from config import Config, SnowflakeImpl
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
# Creates an instance of the flask application
app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
migrate = Migrate(app, db)
from app import routes, models
sqlalchemy.exc.StatementError: (sqlalchemy.exc.ProgrammingError) (snowflake.connector.errors.ProgrammingError) 000904 (42000): SQL compilation error: error line 1 at position 7
invalid identifier 'ID_SEQ.NEXTVAL' [SQL: 'INSERT INTO user (id, username, email, password) VALUES (%(id)s, %(username)s, %(email)s, %(password_hash)s)'] [parameters: [{'email': 'jtest#test.net', 'username': 'Jordan', 'password': None}]] (Background on this error at: http://sqlalche.me/e/f405)
This is the error I am receiving, from what I've read online this should work but it's feeding back an 'invalid identifier' error.
Found the solution, since I am using the flask migrate package I went into the versions folder and observed in the migrate script for my User table my 'Sequence' function was not being included. It was causing my ID to have an Invalid Identifier error.
def upgrade():
op.create_table('user',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('username', sa.String(length=64), nullable=True),
sa.Column('email', sa.String(length=120), nullable=True),
sa.Column('password_hash', sa.String(length=128), nullable=True),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('email'),
sa.UniqueConstraint('username')
)
I defined table name users_table and run db.create_all() to create the table, but get error "no such table user_table" on commit for updating user info.
How I test :
(under /project) python3 manage.py shell
>>> u = User(email='foo#bar.com', username='foobar', password='player')
>>> db.create_all()
>>> db.session.add(u)
>>> db.session.commit() # with following error message
Traceback (most recent call last):
File "C:\...\Python\Python36-32\lib\site-packages\sqlalchemy\engine\base.py", line 1182, in _execute_context
context)
File "C:\...\Python\Python36-32\lib\site-packages\sqlalchemy\engine\default.py", line 470, in do_execute
cursor.execute(statement, parameters)
sqlite3.OperationalError: no such table: users_table
...
...
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: users_table
/project/app/_init_.py:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from config import config
db = SQLAlchemy()
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
db.init_app(app)
return app
/project/app/models.py:
import os
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash
from flask import Flask
basedir = os.path.abspath(os.path.dirname(__file__))
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'data.sqlite')
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
db = SQLAlchemy(app)
class User(db.Model):
__tablename__ = 'users_table'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(64), unique=True, index=True)
username = db.Column(db.String(64), unique=True, index=True)
password_hash = db.Column(db.String(128))
def __repr__(self):
return '<User %r>' % self.username
#property
def password(self):
raise AttributeError('Password is not a readable attribute')
#password.setter
def password(self, password):
self.password_hash = generate_password_hash(password)
project/config.py:
import os
basedir = os.path.abspath(os.path.dirname(\__file__))
class Config:
SECRET_KEY = os.environ.get('SECRET_KEY') or 'fhuaioe7832of67^&*T#oy93'
SQLALCHEMY_COMMIT_ON_TEARDOWN = True
#staticmethod
def init_app(app):
pass
class DevelopmentConfig(Config):
DEBUG = True
SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'data.sqlite')
config = {
'development': DevelopmentConfig,
'default': DevelopmentConfig,
}
project/manage.py:
import os
from app import create_app, db
from app.models import User
from flask_script import Manager, Shell
app = create_app(os.getenv('FLASK_CONFIG') or 'default')
manager = Manager(app)
def make_shell_context():
return dict(app=app, db=db, User=User)
manager.add_command("shell", Shell(make_context=make_shell_context))
if __name__ == '__main__':
manager.run()
I just got done setting up a Flask app and I dealt with this kind of problem.
I strongly suspect the problem here is that the instance of db that you are creating in __init__.py is unaware of the contents of models.py, including the User class. The db object in __init__.py is a totally separate object from the db you are creating in models.py. So when you run db.create_all() in __init__.py, it is checking the list of tables that it knows about and isn't finding any. I ran into this exact issue.
What I discovered is that the models (like User) are registered with the particular db object that is listed in the model's class definition (e.g. class User(db.Model):).
So basically my understanding is that the way to fix this is to run db.create_all() using the same instance of db that is being used to define the models. In other words, run db.create_all() from within models.py.
Here's my code so you can see how I have it set up:
app.py:
#!flask/bin/python
import os
from flask import Flask
class CustomFlask(Flask):
jinja_options = Flask.jinja_options.copy()
jinja_options.update(dict(
variable_start_string='%%', # Default is '{{', I'm changing this because Vue.js uses '{{' / '}}'
variable_end_string='%%',
))
app = CustomFlask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'
import yaml
if os.environ['SERVER_ENVIRONMENT'] == 'PRODUCTION':
config_filename = "production.yaml"
elif os.environ['SERVER_ENVIRONMENT'] == 'LOCAL':
config_filename = "local.yaml"
else:
config_filename = "local.yaml"
base_directory = path = os.path.dirname(os.path.realpath(__file__))
with open(base_directory + "/config/" + config_filename) as config_file:
config = yaml.load(config_file)
db_config = config['database']
SQLALCHEMY_DATABASE_URI = "mysql+mysqlconnector://{username}:{password}#{hostname}/{databasename}".format(
username=db_config['username'],
password=db_config['password'],
hostname=db_config['hostname'],
databasename=db_config['databasename'],
)
app.config["SQLALCHEMY_DATABASE_URI"] = SQLALCHEMY_DATABASE_URI
app.config["SQLALCHEMY_POOL_RECYCLE"] = 299
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy(app)
db.app = app
def clear_the_template_cache():
app.jinja_env.cache = {}
app.before_request(clear_the_template_cache)
from flask_login import LoginManager
login_manager = LoginManager()
login_manager.init_app(app)
#login_manager.user_loader
def load_user(email):
from models import User
return User.query.filter_by(email=email).first()
if __name__ == '__main__':
from routes import web_routes
app.register_blueprint(web_routes)
from api import api
app.register_blueprint(api)
# To get PyCharm's debugger to work, you need to have "debug=False, threaded=True"
#app.run(debug=False, threaded=True)
app.run(debug=True)
models.py:
from app import db
import datetime
from werkzeug.security import generate_password_hash, \
check_password_hash
class Song(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(80))
datetime_created = db.Column(db.DateTime, default=datetime.datetime.utcnow())
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
lines = db.relationship('Line', cascade="all,delete", backref=db.backref('song', lazy='joined'), lazy='dynamic')
is_deleted = db.Column(db.Boolean, default=False)
class Line(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
song_id = db.Column(db.Integer, db.ForeignKey('song.id'))
spans_of_time = db.relationship('SpanOfTime', cascade="all,delete", backref=db.backref('line', lazy='joined'), lazy='dynamic')
class SpanOfTime(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
line_id = db.Column(db.Integer, db.ForeignKey('line.id'))
starting_64th = db.Column(db.Integer) # I'm assuming the highest-granularity desired will be a 1/64th note-length.
length = db.Column(db.Integer) # I guess this'll be in 1/64th notes, so a 1/16th note will be '4'.
content = db.Column(db.String(80))
class User(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
email = db.Column(db.String(80), primary_key=True, unique=True)
display_name = db.Column(db.String(80), default="A Rhymecraft User")
password_hash = db.Column(db.String(200))
datetime_subscription_valid_until = db.Column(db.DateTime, default=datetime.datetime.utcnow() - datetime.timedelta(days=1))
datetime_joined = db.Column(db.DateTime, default=datetime.datetime.utcnow())
songs = db.relationship('Song', cascade="all,delete", backref=db.backref('user', lazy='joined'), lazy='dynamic')
def __init__(self, email, password):
self.email = email
self.set_password(password)
def __repr__(self):
return '<User %r>' % self.email
def set_password(self, password):
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
def is_authenticated(self):
return True
def is_active(self):
return True
def is_anonymous(self):
return False
def get_id(self):
return str(self.email)
def init_db():
db.create_all()
# Create a test user
new_user = User('a#a.com', 'aaaaaaaa')
new_user.display_name = 'Nathan'
db.session.add(new_user)
db.session.commit()
new_user.datetime_subscription_valid_until = datetime.datetime(2019, 1, 1)
db.session.commit()
if __name__ == '__main__':
init_db()
Very simple solution: in the app.py or main.py you can just add these lines of code for fixing this issue:
#app.before_first_request
def create_tables():
db.create_all()
In your case, require to add following code into __init__.py:
from models import User, Role
#app.shell_context_processor
def make_shell_context():
return dict(db=db, User=User, Role=Role)
then you do your previous works, it's all work.
I run into the same problem, after doing a YT tutorial. I solved it by adding this code at the end of my __init__.py
from .models import User, Post
with app.app_context():
db.create_all()
Sidenote: Most tutorials don't use the with app.app_context(): . I think there was a update in flask, which is why this is needed. This caused errors in my code and maybe it helps someone who reads this.
I would like to mention that it was the flask tutorial from "corey schafer" after "part 6 - user authentication", and the error appeared when i ran some tests. just in case anyone else is doing the exact same tutorial and therfore finds it easier to identify my answer as helpful. I am not mentioning the creater for advertisement. I hope this is ok.
Create a folder named "instance" in the root directory and move your database file to that folder.