I'm programming a Website with Authentification while using the Flask Framework. I've tried every solution that i found on the internet but nothing worked for me.
My first idea was, that the Project Structure was corrupt. e.g. missing imports from other files. But thats not the problem i think.
My models.py File:
from flask_login import UserMixin, LoginManager
from flaskapp import db, login_manager
#login_manager.user_loader
def get_user(user):
try:
return get_id(user)
except:
return None
class User(db.Model,UserMixin):
id =db.Column(db.Integer, primary_key=True)
username =db.Column(db.String(20),unique=True, nullable=False)
email =db.Column(db.String(120), unique=True, nullable=False)
password =db.Column(db.String(60), nullable=False)
powerlevel =db.Column(db.Integer, nullable=False)
def is_authenticated(self):
return True
def is_active(self):
return True
def is_anonymous(self):
return False
def get_id(self):
return int(self.id)
def __repr__(self):
return f"User('{self.username}', '{self.email}', '{self.powerlevel}')"
My init.py File:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from flask_login import LoginManager
app = Flask(__name__)
app.config['SECRET_KEY'] = 'xxx'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'
db = SQLAlchemy(app)
bcrypt = Bcrypt(app)
login_manager = LoginManager(app)
login_manager.login_view = 'login'
login_manager = login_message_category = 'info'
from flaskapp import routes
When running the WebApp using:
export FLASK_APP=run.py DEBUG=TRUE
flask run
Following Error Message Occurs:
Traceback (most recent call last):
File "/home/osboxes/.local/bin/flask", line 11, in <module>
sys.exit(main())
File "/home/osboxes/.local/lib/python3.6/site-packages/flask/cli.py", line 966, in main
cli.main(prog_name="python -m flask" if as_module else None)
File "/home/osboxes/.local/lib/python3.6/site-packages/flask/cli.py", line 586, in main
return super(FlaskGroup, self).main(*args, **kwargs)
File "/home/osboxes/.local/lib/python3.6/site-packages/click/core.py", line 717, in main
rv = self.invoke(ctx)
File "/home/osboxes/.local/lib/python3.6/site-packages/click/core.py", line 1137, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/home/osboxes/.local/lib/python3.6/site-packages/click/core.py", line 956, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/home/osboxes/.local/lib/python3.6/site-packages/click/core.py", line 555, in invoke
return callback(*args, **kwargs)
File "/home/osboxes/.local/lib/python3.6/site-packages/click/decorators.py", line 64, in new_func
return ctx.invoke(f, obj, *args, **kwargs)
File "/home/osboxes/.local/lib/python3.6/site-packages/click/core.py", line 555, in invoke
return callback(*args, **kwargs)
File "/home/osboxes/.local/lib/python3.6/site-packages/flask/cli.py", line 848, in run_command
app = DispatchingApp(info.load_app, use_eager_loading=eager_loading)
File "/home/osboxes/.local/lib/python3.6/site-packages/flask/cli.py", line 305, in __init__
self._load_unlocked()
File "/home/osboxes/.local/lib/python3.6/site-packages/flask/cli.py", line 330, in _load_unlocked
self._app = rv = self.loader()
File "/home/osboxes/.local/lib/python3.6/site-packages/flask/cli.py", line 388, in load_app
app = locate_app(self, import_name, name)
File "/home/osboxes/.local/lib/python3.6/site-packages/flask/cli.py", line 240, in locate_app
__import__(module_name)
File "/home/osboxes/Desktop/HMI/run.py", line 1, in <module>
from flaskapp import app
File "/home/osboxes/Desktop/HMI/flaskapp/__init__.py", line 21, in <module>
from flaskapp import routes
File "/home/osboxes/Desktop/HMI/flaskapp/routes.py", line 6, in <module>
from flaskapp.models import User
File "/home/osboxes/Desktop/HMI/flaskapp/models.py", line 7, in <module>
#login_manager.user_loader
AttributeError: 'str' object has no attribute 'user_loader'
Right now i don't know what else could be the problem.
If i forgot to supply some code for solving the error, let me know.
Thank you for your Help!
First, your User.get_id should be returning unicode not an int. The documentation mentions this, along with an example:
This method must return a unicode that uniquely identifies this user,
and can be used to load the user from the user_loader callback. Note
that this must be a unicode - if the ID is natively an int or some
other type, you will need to convert it to unicode. (Your User
Class)
So that needs to be changed to:
def get_id(self):
return unicode(self.id)
Next up, your user_loader. From the docs:
This sets the callback for reloading a user from the session. The
function you set should take a user ID (a unicode) and return a user
object, or None if the user does not exist.
Which would mean adjusting your user_loader to be something like:
#login_manager.user_loader
def get_user(user_id):
try:
return User.query.get(int(user_id))
except:
return None
Also, you have an error here, which is likely the direct cause of the error:
login_manager = login_message_category = 'info'
So your taking your login_manager and replacing it with a string with the contents 'info'. So later when your app tries to access login_manager.user_loader it's failing, because a string 'info' doesn't have a user_loader method.
Changing it to the below should fix the error. Though the other issues addressed above also need to be implemented.
login_manager.login_message_category = 'info'
You have used the login_manager = LoginManager(app) you are creating an object along with the configuration. Insider of that create an object first and configure the object in 2 steps.
login_manager = LoginManager()
login_manager.init_app(app)
for more reference please check the link here[https://flask-login.readthedocs.io/en/latest/]
you may need to update in your init.py file.
Related
Alembic's autogenerate keeps throwing this error and it's rather mysterious to me:
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
Traceback (most recent call last):
File "/home/mas/projects/icc/icc2-backend/.venv/bin/alembic", line 8, in <module>
sys.exit(main())
File "/home/mas/projects/icc/icc2-backend/.venv/lib/python3.9/site-packages/alembic/config.py", line 581, in main
CommandLine(prog=prog).main(argv=argv)
File "/home/mas/projects/icc/icc2-backend/.venv/lib/python3.9/site-packages/alembic/config.py", line 575, in main
self.run_cmd(cfg, options)
File "/home/mas/projects/icc/icc2-backend/.venv/lib/python3.9/site-packages/alembic/config.py", line 552, in run_cmd
fn(
File "/home/mas/projects/icc/icc2-backend/.venv/lib/python3.9/site-packages/alembic/command.py", line 214, in revision
script_directory.run_env()
File "/home/mas/projects/icc/icc2-backend/.venv/lib/python3.9/site-packages/alembic/script/base.py", line 489, in run_env
util.load_python_file(self.dir, "env.py")
File "/home/mas/projects/icc/icc2-backend/.venv/lib/python3.9/site-packages/alembic/util/pyfiles.py", line 98, in load_python_file
module = load_module_py(module_id, path)
File "/home/mas/projects/icc/icc2-backend/.venv/lib/python3.9/site-packages/alembic/util/compat.py", line 184, in load_module_py
spec.loader.exec_module(module)
File "<frozen importlib._bootstrap_external>", line 855, in exec_module
File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
File "/home/mas/projects/icc/icc2-backend/alembic/env.py", line 84, in <module>
run_migrations_online()
File "/home/mas/projects/icc/icc2-backend/alembic/env.py", line 78, in run_migrations_online
context.run_migrations()
File "<string>", line 8, in run_migrations
File "/home/mas/projects/icc/icc2-backend/.venv/lib/python3.9/site-packages/alembic/runtime/environment.py", line 846, in run_migrations
self.get_context().run_migrations(**kw)
File "/home/mas/projects/icc/icc2-backend/.venv/lib/python3.9/site-packages/alembic/runtime/migration.py", line 511, in run_migrations
for step in self._migrations_fn(heads, self):
File "/home/mas/projects/icc/icc2-backend/.venv/lib/python3.9/site-packages/alembic/command.py", line 190, in retrieve_migrations
revision_context.run_autogenerate(rev, context)
File "/home/mas/projects/icc/icc2-backend/.venv/lib/python3.9/site-packages/alembic/autogenerate/api.py", line 444, in run_autogenerate
self._run_environment(rev, migration_context, True)
File "/home/mas/projects/icc/icc2-backend/.venv/lib/python3.9/site-packages/alembic/autogenerate/api.py", line 483, in _run_environment
compare._populate_migration_script(
File "/home/mas/projects/icc/icc2-backend/.venv/lib/python3.9/site-packages/alembic/autogenerate/compare.py", line 25, in _populate_migration_script
_produce_net_changes(autogen_context, upgrade_ops)
File "/home/mas/projects/icc/icc2-backend/.venv/lib/python3.9/site-packages/alembic/autogenerate/compare.py", line 50, in _produce_net_changes
comparators.dispatch("schema", autogen_context.dialect.name)(
File "/home/mas/projects/icc/icc2-backend/.venv/lib/python3.9/site-packages/alembic/util/langhelpers.py", line 303, in go
fn(*arg, **kw)
File "/home/mas/projects/icc/icc2-backend/.venv/lib/python3.9/site-packages/alembic/autogenerate/compare.py", line 75, in _autogen_for_tables
[(table.schema, table.name) for table in autogen_context.sorted_tables]
File "/home/mas/projects/icc/icc2-backend/.venv/lib/python3.9/site-packages/alembic/util/langhelpers.py", line 230, in __get__
obj.__dict__[self.__name__] = result = self.fget(obj)
File "/home/mas/projects/icc/icc2-backend/.venv/lib/python3.9/site-packages/alembic/autogenerate/api.py", line 362, in sorted_tables
result.extend(m.sorted_tables)
TypeError: 'property' object is not iterable
My models are thus:
# app/models/mixins.py
from app import db
from sqlalchemy.ext.declarative import declared_attr, as_declarative
#as_declarative()
class Base(db.Model):
"""This Base class does nothing. It is here in case I need to expand
implement something later. I feel like it's a good early practice.
Attributes
----------
id : int
The basic primary key id number of any class.
Notes
-----
The __tablename__ is automatically set to the class name lower-cased.
There's no need to mess around with underscores, that just confuses the
issue and makes programmatically referencing the table more difficult.
"""
__abstract__ = True
id = db.Column(db.Integer, primary_key=True)
#declared_attr
def __tablename__(cls):
return cls.__name__.lower()
# app/models/annotations.py
from datetime import datetime as dt
from app import db
from app.models.mixins import Base
class Annotation(Base):
bookid = db.Column(db.Integer)
author = db.Column(db.String)
created = db.Column(db.DateTime)
edits = db.relationship('Edit', back_populates='annotation')
HEAD = db.relationship('Edit',
primaryjoin='Edit.annotation_id==Annotation.id',
uselist=False)
def __init__(self, book, author, start, end, text, *args, **kwargs):
self.created = dt.now()
self.bookid = book
self.author = author
super().__init__(*args, **kwargs)
self.edits.append(Edit(author, start, end, text))
class Edit(Base):
annotation_id = db.Column(db.Integer, db.ForeignKey('annotation.id'),
index=True)
text = db.Column(db.Text)
editor = db.Column(db.String)
start = db.Column(db.Integer)
end = db.Column(db.Integer)
created = db.Column(db.DateTime)
annotation = db.relationship('Annotation', back_populates='edits')
def __init__(self, editor, start, end, text, *args, **kwargs):
self.editor = editor
self.start, self.end = start, end
self.text = text
self.created = dt.utcnow()
super().__init__(*args, **kwargs)
And because I'm not sure if it's relevant, my alembic/env.py
from logging.config import fileConfig
from sqlalchemy import engine_from_config
from sqlalchemy import pool
from alembic import context
import os, inspect, sys
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir)
from config import Config
config = context.config # alembic
config.set_main_option('sqlalchemy.url', Config.SQLALCHEMY_DATABASE_URI)
print(Config.SQLALCHEMY_DATABASE_URI)
# Interpret the config file for Python logging.
# This line sets up loggers basically.
fileConfig(config.config_file_name)
from app import db
target_metadata = db.MetaData
# other values from the config, defined by the needs of env.py,
# can be acquired:
# my_important_option = config.get_main_option("my_important_option")
# ... etc.
def run_migrations_offline():
"""Run migrations in 'offline' mode.
This configures the context with just a URL
and not an Engine, though an Engine is acceptable
here as well. By skipping the Engine creation
we don't even need a DBAPI to be available.
Calls to context.execute() here emit the given string to the
script output.
"""
url = config.get_main_option("sqlalchemy.url")
context.configure(
url=url,
target_metadata=target_metadata,
literal_binds=True,
dialect_opts={"paramstyle": "named"},
)
with context.begin_transaction():
context.run_migrations()
def run_migrations_online():
"""Run migrations in 'online' mode.
In this scenario we need to create an Engine
and associate a connection with the context.
"""
connectable = engine_from_config(
config.get_section(config.config_ini_section),
prefix="sqlalchemy.",
poolclass=pool.NullPool,
)
with connectable.connect() as connection:
context.configure(
connection=connection, target_metadata=target_metadata
)
with context.begin_transaction():
context.run_migrations()
if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()
The code is all at https://github.com/anno-wiki/icc2-backend if that might help. I'm hoping someone might be able to shed some light on this. Alembic's code is rather abstract and difficult to follow to see why that particular line is having trouble with my configuration. I've used a Base mixin plenty of times before and it's never been a problem.
It seems that by changing target_metadata = db.MetaData to target_metadata = db.metdata fixed the problem, though then the models weren't detected. Importing app.models.Annotation and using Annotation.metadata made the whole thing work.
I'm debugging an error, when I try to query from my database to populate the fields of my FlaskForm, I get the following error:
Traceback (most recent call last):
File "manage.py", line 16, in <module>
app = create_app(os.getenv('DVR_CONFIG') or 'default')
File "C:\Users\---\myapp\\app\__init__.py", line 42, in create_app
from .main import main as main_blueprint
File "C:\Users\---\myapp\\app\main\__init__.py", line 5, in <module>
from . import views, errors
File "C:\Users\---\myapp\\app\main\views.py", line 5, in <module>
from .forms import CharacterSelect
File "C:\Users\---\myapp\\app\main\forms.py", line 15, in <module>
class CharacterSelect(FlaskForm):
File "C:\Users\---\myapp\\app\main\forms.py", line 17, in CharacterSelect
user = User.query.filter_by(unique_name=session.get('unique_name')).first()
File "C:\Python27\lib\site-packages\flask_sqlalchemy\__init__.py", line 500, in __get__
return type.query_class(mapper, session=self.sa.session())
File "C:\Python27\lib\site-packages\sqlalchemy\orm\scoping.py", line 78, in __call__
return self.registry()
File "C:\Python27\lib\site-packages\sqlalchemy\util\_collections.py", line 990, in __call__
return self.registry.setdefault(key, self.createfunc())
File "C:\Python27\lib\site-packages\flask_sqlalchemy\__init__.py", line 771, in create_session
return SignallingSession(self, **options)
File "C:\Python27\lib\site-packages\flask_sqlalchemy\__init__.py", line 153, in __init__
self.app = app = db.get_app()
File "C:\Python27\lib\site-packages\flask_sqlalchemy\__init__.py", line 922, in get_app
raise RuntimeError('application not registered on db '
RuntimeError: application not registered on db instance and no application bound to current context
Here is the offending code:
from ..models import User
class CharacterSelect(FlaskForm):
user = User.query.filter_by(unique_name=session.get('unique_name')).first()
charId0 = user.characterId_0
charId1 = user.characterId_1
charId2 = user.characterId_2
user_list = [charId0, 'Char0', charId1, 'Char1', charId2, 'Char2']
new_user_list = [x for x in user_list if x is not None]
selectedUser = SelectField(u'Character Select', choices=user_list)
From researching this error, it appears Flask doesn't know which app my DB is attached to. Also most of the stackoverflow answers I have seen recommend using:
with app.app_context():
:
:
db.create_all()
However, from working through Miguels Flask Book and Flasky blog, he doesn't seem to need to use "with app.app_context()" and only uses "db.create_all()" in his unit test code. Miguel inits the DB like so:
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)
Any help in debugging and understanding this error is much appreciated!
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
Many things are nor clear from your code snippet. What is obvious however is that you have to have your db.init_app(app) inside your create_app() function. Then you would return app object from the function. Most preferably in different module i.e. manage.py (this really depends on your application structure)
from somewhere import create_app
app = create_app(config_name)
if __name__ == "__main__":
app.run()
Now variable app is your application instance with db registered.
Someone has pointed me to the FlaskForm Docs, where the is a pretty sparse example.
Esentially I need to create the tuple list in my views.py and pass it into my Form Object, see below for details:
views.py:
user = g.user
charId0 = user.characterId_0
charId1 = user.characterId_1
charId2 = user.characterId_2
user_list = [(charId0, 'Char0'), (charId1, 'Char1'), (charId2, 'Char2')]
form = CharacterSelect(request.form)
form.selectedUser.choices = user_list
forms.py:
class CharacterSelect(FlaskForm):
selectedUser = SelectField(u'Character Select', choices=[])
I have a function called generate_csrf_token which is located in package commons.formsecurity containing the following code.
import random
import string
from flask import session
def generate_csrf_token():
if '_csrf_token' not in session:
state = ''.join(random.choice(string.ascii_uppercase + string.digits)
for x in xrange(32))
session['_csrf_token'] = state
return session['_csrf_token']
I am calling this in my create_app function.
from flask import Flask
from routes_manager import configure_blueprints
from error_handling import configure_error_handling
from flask import session
from flask.ext.session import Session
from commons.formsecurity import generate_csrf_token
def create_app():
"""Create the Flask App"""
app = Flask(__name__)
app.secret_key = 'lalalalalala'
app.jinja_env.globals['csrf_token'] = generate_csrf_token()
configure_blueprints(app)
configure_error_handling(app)
return app
create_app is called from main.py
from app import create_app
app = create_app()
"""Run the clients"""
if __name__ == '__main__':
app.run(debug=True)
When I run my Flask application. I get the following error.
ERROR 2017-05-25 12:12:50,720 wsgi.py:263]
Traceback (most recent call last):
File "C:\Program Files (x86)\Google\google_appengine\google\appengine\runtime\wsgi.py", line 240, in Handle
handler = _config_handle.add_wsgi_middleware(self._LoadHandler())
File "C:\Program Files (x86)\Google\google_appengine\google\appengine\runtime\wsgi.py", line 299, in _LoadHandler
handler, path, err = LoadObject(self._handler)
File "C:\Program Files (x86)\Google\google_appengine\google\appengine\runtime\wsgi.py", line 85, in LoadObject
obj = __import__(path[0])
File "C:\Code\App-Engine\cfc-melbourne-website\main.py", line 3, in <module>
app = create_app()
File "C:\Code\App-Engine\cfc-melbourne-website\app\__init__.py", line 12, in create_app
app.jinja_env.globals['csrf_token'] = generate_csrf_token()
File "C:\Code\App-Engine\cfc-melbourne-website\app\commons\formsecurity.py", line 7, in generate_csrf_token
if '_csrf_token' not in session:
File "lib\werkzeug\local.py", line 379, in <lambda>
__contains__ = lambda x, i: i in x._get_current_object()
File "lib\werkzeug\local.py", line 306, in _get_current_object
return self.__local()
File "lib\flask\globals.py", line 37, in _lookup_req_object
raise RuntimeError(_request_ctx_err_msg)
RuntimeError: Working outside of request context.
This typically means that you attempted to use functionality that needed
an active HTTP request. Consult the documentation on testing for
information about how to avoid this problem.
Where is the best place to call the following
app.jinja_env.globals['csrf_token'] = generate_csrf_token()
If you don't call the generate_csrf_token() function, and instead store the reference to the function, you can call it in your Jinja templates (which will be in the context where a request is available).
So replace
app.jinja_env.globals['csrf_token'] = generate_csrf_token()
With
app.jinja_env.globals['csrf_token'] = generate_csrf_token
And in your templates, use:
<input name=_csrf_token type=hidden value="{{ csrf_token() }}">
I've been trying to make the code on https://github.com/graup/flask-restless-security work for a while. After I had failed to incorporate this in my own code I decided to simply just use this prepared code. However when I try to run server.py it raises the error below. Origin of the error is apimanager of flask-restless. I opened an issue on git however apparently the project is not maintained anymore. How can I make this work?
Traceback (most recent call last):
File "E:/WEB/Project1/app/server.py", line 62, in
include_columns=['id', 'data1', 'data2', 'user_id'])
File "E:\WEB\Project1\flask\lib\site-packages\flask_restless\manager.py", line 698, in create_api
blueprint = self.create_api_blueprint(app=app, *args, **kw)
File "E:\WEB\Project1\flask\lib\site-packages\flask_restless\manager.py", line 566, in create_api_blueprint
pk_name = primary_key or primary_key_name(model)
File "E:\WEB\Project1\flask\lib\site-packages\flask_restless\helpers.py", line 232, in primary_key_name
pk_names = primary_key_names(model)
File "E:\WEB\Project1\flask\lib\site-packages\flask_restless\helpers.py", line 214, in primary_key_names
return [key for key, field in inspect.getmembers(model)
File "c:\python27\Lib\inspect.py", line 252, in getmembers
value = getattr(object, key)
File "E:\WEB\Project1\flask\lib\site-packages\flask_sqlalchemy_init_.py", line 498, in get
return type.query_class(mapper, session=self.sa.session())
File "E:\WEB\Project1\flask\lib\site-packages\sqlalchemy\orm\scoping.py", line 78, in call
return self.registry()
File "E:\WEB\Project1\flask\lib\site-packages\sqlalchemy\util_collections.py", line 990, in call
return self.registry.setdefault(key, self.createfunc())
File "E:\WEB\Project1\flask\lib\site-packages\sqlalchemy\orm\session.py", line 2829, in call
return self.class_(**local_kw)
File "E:\WEB\Project1\flask\lib\site-packages\flask_sqlalchemy_init_.py", line 143, in init
self.app = app = db.get_app()
File "E:\WEB\Project1\flask\lib\site-packages\flask_sqlalchemy_init_.py", line 957, in get_app
'application not registered on db instance and no application'
RuntimeError: application not registered on db instance and no applicationbound to current context
server.py
from database import db
from application import app
from flask_restless import APIManager
from models import SomeStuff
apimanager = APIManager(app, flask_sqlalchemy_db=db)
apimanager.create_api(SomeStuff,
methods=['GET', 'POST', 'DELETE', 'PUT'],
url_prefix='/api/v1',
collection_name='free_stuff',
include_columns=['id', 'data1', 'data2', 'user_id'])
application.py
from flask import Flask
app = Flask(__name__)
app.config.from_object('config.DevelopmentConfig')
database.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
models.py
from database import db
from flask_security import UserMixin, RoleMixin, SQLAlchemyUserDatastore
class SomeStuff(db.Model):
__tablename__ = 'somestuff'
id = db.Column(db.Integer, primary_key=True)
data1 = db.Column(db.Integer)
data2 = db.Column(db.String(10))
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=True)
user = db.relationship(User, lazy='joined', join_depth=1, viewonly=True)
The error you have now:
flask_sqlalchemy_init_.py
RuntimeError: application not registered on db instance and no
applicationbound to current context
is at flask_sqlalchemy usage, that not define a app instance.
The solution is register the application on db instance.
from flask_sqlalchemy import SQLAlchemy
from application import app
db = SQLAlchemy(app)
I'm most probably missing some basic concept here, but I have tried to create something like simple code review application and trying to follow this docs when designing DB schema:
http://flask-sqlalchemy.pocoo.org/2.1/models/#one-to-many-relationships
Part (which can be used to reproduce) of my model is:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# all the imports
from flask import Flask, request, session, g, redirect, url_for, \
abort, render_template, flash
from flask_sqlalchemy import SQLAlchemy
# configuration
DEBUG = True
SECRET_KEY = 'development key'
SQLALCHEMY_DATABASE_URI = 'sqlite:////tmp/test.db'
# create our little application :)
app = Flask(__name__)
app.config.from_object(__name__) # load all uppercase constants here (see configuration section above)
db = SQLAlchemy(app)
class Repo(db.Model):
id = db.Column(db.Integer, primary_key=True)
repo = db.Column(db.String(120), unique=True)
commits = db.relationship('Commit',
backref=db.backref('repo', lazy='dynamic'))
def __init__(self, repo=None):
self.repo = repo
def __repr__(self):
return '<Repo %r>' % (self.repo)
class Commit(db.Model):
id = db.Column(db.Integer, primary_key=True)
repo_id = db.Column(db.Integer, db.ForeignKey('repo.id'))
commit = db.Column(db.String(64))
def __init__(self, repo_id=None, commit=None):
self.repo_id = repo_id
self.commit = commit
def __repr__(self):
return '<Commit %r (repo %r)>' % (self.commit, self.repo_id)
if __name__ == '__main__':
app.run()
I get traceback when I attempt to create first repo:
>>> import code_review
>>> code_review.db.create_all()
>>> code_review.Repo('Pokus.git')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 2, in __init__
File "/usr/lib64/python2.7/site-packages/sqlalchemy/orm/instrumentation.py", line 347, in _new_state_if_none
state = self._state_constructor(instance, self)
File "/usr/lib64/python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 747, in __get__
obj.__dict__[self.__name__] = result = self.fget(obj)
File "/usr/lib64/python2.7/site-packages/sqlalchemy/orm/instrumentation.py", line 177, in _state_constructor
self.dispatch.first_init(self, self.class_)
File "/usr/lib64/python2.7/site-packages/sqlalchemy/event/attr.py", line 256, in __call__
fn(*args, **kw)
File "/usr/lib64/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 2860, in _event_on_first_init
configure_mappers()
File "/usr/lib64/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 2756, in configure_mappers
mapper._post_configure_properties()
File "/usr/lib64/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 1710, in _post_configure_properties
prop.init()
File "/usr/lib64/python2.7/site-packages/sqlalchemy/orm/interfaces.py", line 183, in init
self.do_init()
File "/usr/lib64/python2.7/site-packages/sqlalchemy/orm/relationships.py", line 1632, in do_init
self._generate_backref()
File "/usr/lib64/python2.7/site-packages/sqlalchemy/orm/relationships.py", line 1863, in _generate_backref
mapper._configure_property(backref_key, relationship)
File "/usr/lib64/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 1614, in _configure_property
prop.post_instrument_class(self)
File "/usr/lib64/python2.7/site-packages/sqlalchemy/orm/interfaces.py", line 526, in post_instrument_class
self.strategy.init_class_attribute(mapper)
File "/usr/lib64/python2.7/site-packages/sqlalchemy/orm/dynamic.py", line 33, in init_class_attribute
"uselist=False." % self.parent_property)
sqlalchemy.exc.InvalidRequestError: On relationship Commit.repo, 'dynamic' loaders cannot be used with many-to-one/one-to-one relationships and/or uselist=False.
OK, I was confused by various guides and looks like this is what I want:
- commits = db.relationship('Commit',
- backref=db.backref('repo', lazy='dynamic'))
+ commits = db.relationship('Commit',
+ backref='repo', lazy='dynamic')