I have a sqlalchemy model that I am searching with flask-whooshalchemy. I was looking to include the output of a method in the search fields but can't figure out how it's done or if it's even possible. The flask-whooshalchemy documentation is a little limited.
I'm currently trying something like this:
class Trade(db.Model):
__searchable__ = [
'species', 'nature', 'ability', 'move1', 'move2', 'move3', 'move4', 'ivSpread']
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
dex_no = db.Column(db.Integer)
species = db.Column(db.String(30))
male = db.Column(db.Boolean)
female = db.Column(db.Boolean)
nature = db.Column(db.String(30))
ability = db.Column(db.String(30))
iv_hp = db.Column(db.Integer)
iv_atk = db.Column(db.Integer)
iv_def = db.Column(db.Integer)
iv_spa = db.Column(db.Integer)
iv_spd = db.Column(db.Integer)
iv_spe = db.Column(db.Integer)
move1 = db.Column(db.String(30))
move2 = db.Column(db.String(30))
move3 = db.Column(db.String(30))
move4 = db.Column(db.String(30))
def ivSpread(self):
ivs = [
self.iv_hp,
self.iv_atk,
self.iv_def,
self.iv_spa,
self.iv_spd,
self.iv_spe
]
return "/".join(ivs)
def __repr__(self):
return '<Post %r: %r>' % (self.owner.nickname, self.species)
Let me know if I can provide any more information. Suggestions of alternate modules to use is fine too, I'm sure there could be something more powerful than flask-whooshalchemy out there. It hasn't been pushed to in 2 years after all.
e: Using the above as is and with the #property suggestion provided by Mark Hildreth below, I get the following traceback.
whoosh.fields.UnknownFieldError
UnknownFieldError: No field named 'ivSpread' in <Schema: ['ability', 'gender', 'id', 'move1', 'move2', 'move3', 'move4', 'nature', 'species']>
Traceback (most recent call last):
File "c:\Python27\lib\site-packages\flask\app.py", line 1701, in __call__
return self.wsgi_app(environ, start_response)
File "c:\Python27\lib\site-packages\flask\app.py", line 1689, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "c:\Python27\lib\site-packages\flask\app.py", line 1687, in wsgi_app
response = self.full_dispatch_request()
File "c:\Python27\lib\site-packages\flask\app.py", line 1360, in full_dispatch_request
rv = self.handle_user_exception(e)
File "c:\Python27\lib\site-packages\flask\app.py", line 1358, in full_dispatch_request
rv = self.dispatch_request()
File "c:\Python27\lib\site-packages\flask\app.py", line 1344, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "c:\Users\Shane\Documents\Coding\python\flask\trade_lister\app\views.py", line 172, in new_trade
db.session.commit()
File "c:\Python27\lib\site-packages\sqlalchemy\orm\scoping.py", line 114, in do
return getattr(self.registry(), name)(*args, **kwargs)
File "c:\Python27\lib\site-packages\sqlalchemy\orm\session.py", line 703, in commit
self.transaction.commit()
File "c:\Python27\lib\site-packages\sqlalchemy\orm\session.py", line 367, in commit
self.session.dispatch.after_commit(self.session)
File "c:\Python27\lib\site-packages\sqlalchemy\event.py", line 319, in __call__
fn(*args, **kw)
File "c:\Python27\lib\site-packages\flask_sqlalchemy\__init__.py", line 170, in session_signal_after_commit
models_committed.send(session.app, changes=d.values())
File "c:\Python27\lib\site-packages\blinker\base.py", line 267, in send
for receiver in self.receivers_for(sender)]
File "c:\Python27\lib\site-packages\flask_whooshalchemy.py", line 256, in _after_flush
writer.update_document(**attrs)
File "c:\Python27\lib\site-packages\whoosh\writing.py", line 477, in update_document
self.add_document(**fields)
File "c:\Python27\lib\site-packages\whoosh\writing.py", line 730, in add_document
self._check_fields(schema, fieldnames)
File "c:\Python27\lib\site-packages\whoosh\writing.py", line 718, in _check_fields
% (name, schema))
UnknownFieldError: No field named 'ivSpread' in <Schema: ['ability', 'gender', 'id', 'move1', 'move2', 'move3', 'move4', 'nature', 'species']>
I don't know nearly enough about Woosh or Flask-Wooshalchemy, so this might be wrong, but I imagine you might be able to do something like this...
class Trade(db.Model):
#...
#property
def ivSpread(self):
#...
This uses a property to make the method call look like an attribute, so instead of doing...
t = Trade(...)
print t.ivSpread()
...you would do...
t = Trade(...)
print t.ivSpread
This would be necessary because Flask-WooshAlchemy seems to be assuming that the searchable item is an attribute, and at this point it's just pulling the method without calling it.
If you need to have ivSpread stay a method, you can use a wrapper:
class Trade(db.Model):
#...
def ivSpread(self):
#...
#property
def ivSpreadProp(self):
return self.ivSpread()
Then you would need to make ivSpreadProp searchable rathe rthan ivSpread.
Edit:
Looks like what you are trying to do is not currently possible. See here:
searchable = set(model.__searchable__)
for field in model.__table__.columns:
if field.primary_key:
schema[field.name] = whoosh.fields.ID(stored=True, unique=True)
primary = field.name
if field.name in searchable and isinstance(field.type,
(sqlalchemy.types.Text, sqlalchemy.types.String,
sqlalchemy.types.Unicode)):
schema[field.name] = whoosh.fields.TEXT(
analyzer=StemmingAnalyzer())
Flask-WhooshAlchemy assumes that items in the __searchable__ attribute are going to be columns defined by your model using SQLAlchemy. Flask-WhooshAlchemy would need to allow you to achieve your goal cleanly.
Related
I have a Flask-SQLAlchemy association table named 'followers' and when I run the query following query via REPL it runs fine, but when running the code on the Flask application it gives me the error "'AttributeError: 'function' object has no attribute 'c'".
Function calling the query
#app.route('/following/<int:user_id>', methods=['GET'])
#login_required
def following(user_id):
"""
Show all the Tutors the user is following
"""
user = Users.query.get(user_id)
page = request.args.get('page', 1, type=int)
result = db.session.query(Users, Tutors)\
.join(Tutors, Tutors.user_id==Users.id ,full=True)\
.join(followers, Tutors.id == followers.c.followed_id)\
.filter(user_id==followers.c.follower_id).all()
next_url = url_for('index', page=result.next_num) if result.has_next else None
prev_url = url_for('index', page=result.prev_num) if result.has_prev else None
data = {}
data['user'] = []
data['tutor'] = []
rows = len(result.items)
for i in range(rows):
data['user'].append(result.items[i][0])
data['tutor'].append(result.items[i][1])
return render_template('index.html', title='Following',
data=data, rows=rows,
next_url=next_url, prev_url=prev_url)
Just the query
result = db.session.query(Users, Tutors)\
.join(Tutors, Tutors.user_id==Users.id ,full=True)\
.join(followers, Tutors.id == followers.c.followed_id)\
.filter(user_id==followers.c.follower_id).all()
Models
followers = db.Table('followers',
db.Column('follower_id', db.Integer, db.ForeignKey('users.id')),
db.Column('followed_id', db.Integer, db.ForeignKey('tutors.id'))
)
class Users(UserMixin, db.Model):
__tablename__ = 'users'
__table_args__ = {'extend_existing': True}
id = db.Column(db.Integer, primary_key=True)
... (other non-related properties)
followed = db.relationship('Tutors', secondary=followers, lazy='dynamic',
backref=db.backref('followers', lazy='dynamic'))
class Tutors(db.Model):
__tablename__ = 'tutors'
__table_args__ = {'extend_existing': True}
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
... (other non-related properties)
Error traceback
Error on request:
Traceback (most recent call last):
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/werkzeug/serving.py", line 323, in run_wsgi
execute(self.server.app)
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/werkzeug/serving.py", line 312, in execute
application_iter = app(environ, start_response)
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/flask/app.py", line 2464, in __call__
return self.wsgi_app(environ, start_response)
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/flask/app.py", line 2450, in wsgi_app
response = self.handle_exception(e)
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/flask/app.py", line 1867, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/flask/app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/flask/app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/flask/app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/flask/app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/flask/app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/richardnienkotter/Documents/Projects/codetutors/env/lib/python3.8/site-packages/flask_login/utils.py", line 272, in decorated_view
return func(*args, **kwargs)
File "/Users/richardnienkotter/Documents/Projects/codetutors/app/routes.py", line 134, in following
result = db.session.query(Users, Tutors, followers.c.follower_id, followers.c.followed_id)\
AttributeError: 'function' object has no attribute 'c'
Using type() on the Debug Console shows that 'followers' is a function and that's the root of the problem, but why is it being called as a function?
Solution
In routes.py I had the same name for both the view function and the association table, which was causing the problem.
Thanks Abhi for the help :)
please check the file named
"/Users/richardnienkotter/Documents/Projects/codetutors/app/routes.py", line 134, in following
There may be a function named as followers, which is contradicting with your table named as followers.
I understand that one needs to provide default='value' for this kind of situation. I've consulted with solutions over StackOverFlow but couldn't get rid of this error. With or without default I am getting this error while saving from admin forms. Error is in Packeges module at init function. Please advise.
Following is my code:
class Packeges(db.Model):
__tablename__ = 'packages'
id = db.Column(db.Integer, primary_key=True)
package_name = db.Column(db.String(30), default='Add Package Here')
def __init__(self, package_name):
self.package_name = package_name
admin.add_view(ModelView(Packeges, db.session))
class UserSubscription(db.Model):
__tablename__ = 'user_subscription'
id = db.Column(db.Integer, primary_key=True)
user_profile = db.Column(db.String(80), unique=True)
package_name = db.Column(db.Integer, db.ForeignKey(Packeges.id))
packages = db.relationship(Packeges, backref='package')
timestamp = db.Column(db.DateTime)
expiry = db.Column(db.DateTime)
def __init__(self, user_profile, package_name, timestamp, expiry):
self.user_profile = user_profile
self.package_name = package_name
self.timestamp = timestamp
self.expiry = expiry
admin.add_view(ModelView(UserSubscription, db.session))
Traceback:
TypeError
TypeError: __init__() takes exactly 2 arguments (1 given)
Traceback (most recent call last)
File "C:\Users\AliKhan\flask_ecom\env\lib\site-packages\flask\app.py", line 1994, in __call__
return self.wsgi_app(environ, start_response)
File "C:\Users\AliKhan\flask_ecom\env\lib\site-packages\flask\app.py", line 1985, in wsgi_app
response = self.handle_exception(e)
File "C:\Users\AliKhan\flask_ecom\env\lib\site-packages\flask\app.py", line 1540, in handle_exception
reraise(exc_type, exc_value, tb)
File "C:\Users\AliKhan\flask_ecom\env\lib\site-packages\flask\app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "C:\Users\AliKhan\flask_ecom\env\lib\site-packages\flask\app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\Users\AliKhan\flask_ecom\env\lib\site-packages\flask\app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "C:\Users\AliKhan\flask_ecom\env\lib\site-packages\flask\app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Users\AliKhan\flask_ecom\env\lib\site-packages\flask\app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\Users\AliKhan\flask_ecom\env\lib\site-packages\flask_admin\base.py", line 69, in inner
return self._run_view(f, *args, **kwargs)
File "C:\Users\AliKhan\flask_ecom\env\lib\site-packages\flask_admin\base.py", line 368, in _run_view
return fn(self, *args, **kwargs)
File "C:\Users\AliKhan\flask_ecom\env\lib\site-packages\flask_admin\model\base.py", line 1920, in create_view
model = self.create_model(form)
File "C:\Users\AliKhan\flask_ecom\env\lib\site-packages\flask_admin\contrib\sqla\view.py", line 1028, in create_model
Open an interactive python shell in this frameif not self.handle_view_exception(ex):
File "C:\Users\AliKhan\flask_ecom\env\lib\site-packages\flask_admin\contrib\sqla\view.py", line 1011, in handle_view_exception
return super(ModelView, self).handle_view_exception(exc)
File "C:\Users\AliKhan\flask_ecom\env\lib\site-packages\flask_admin\contrib\sqla\view.py", line 1022, in create_model
model = self.model()
Try like below:
def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Hi I had database many to many relation and for bestfriend one to one relationship which works perfectly with sqlalchemy now I change it to postgresql and got the
errornvalidRequestError: On relationship Users.is_bestfriend, 'dynamic' loaders cannot be used with many-to-one/one-to-one relationships and/or uselist=False.
error:
Traceback (most recent call last)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/usr/local/lib/python2.7/dist-packages/flask_login.py", line 756, in decorated_view
elif not current_user.is_authenticated():
File "/usr/local/lib/python2.7/dist-packages/werkzeug/local.py", line 338, in __getattr__
return getattr(self._get_current_object(), name)
File "/usr/local/lib/python2.7/dist-packages/werkzeug/local.py", line 297, in _get_current_object
return self.__local()
File "/usr/local/lib/python2.7/dist-packages/flask_login.py", line 46, in <lambda>
current_user = LocalProxy(lambda: _get_user())
File "/usr/local/lib/python2.7/dist-packages/flask_login.py", line 794, in _get_user
current_app.login_manager._load_user()
File "/usr/local/lib/python2.7/dist-packages/flask_login.py", line 363, in _load_user
return self.reload_user()
File "/usr/local/lib/python2.7/dist-packages/flask_login.py", line 325, in reload_user
user = self.user_callback(user_id)
File "/home/peg/flask-Alembic/app/auth/view.py", line 60, in load_user
return Users.query.get(int(user_id))
File "/usr/local/lib/python2.7/dist-packages/flask_sqlalchemy/__init__.py", line 426, in __get__
mapper = orm.class_mapper(type)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/base.py", line 378, in class_mapper
mapper = _inspect_mapped_class(class_, configure=configure)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/base.py", line 355, in _inspect_mapped_class
mapper._configure_all()
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/mapper.py", line 1129, in _configure_all
configure_mappers()
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/mapper.py", line 2544, in configure_mappers
mapper._post_configure_properties()
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/mapper.py", line 1660, in _post_configure_properties
prop.post_instrument_class(self)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/interfaces.py", line 481, in post_instrument_class
self.strategy.init_class_attribute(mapper)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/dynamic.py", line 31, in init_class_attribute
"uselist=False." % self.parent_property)
InvalidRequestError: On relationship Users.is_bestfriend, 'dynamic' loaders cannot be used with many-to-one/one-to-one relationships and/or uselist=False.
model.py:
friends = db.Table('friends',
db.Column('user_id', db.Integer, db.ForeignKey('users.id')),
db.Column('friend_id', db.Integer, db.ForeignKey('users.id'))
)
class Users(db.Model):
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String(50), index=True)
age= db.Column(db.Integer )
email = db.Column(db.String(50),index=True, unique= True)
bestfriend_id = db.Column(db.Integer, db.ForeignKey('users.id'))
is_bestfriend = db.relationship( 'Users',lazy='dynamic',remote_side=id, post_update=True)
is_friend = db.relationship('Users', #defining the relationship, Users is left side entity
secondary = friends, #indecates association table
primaryjoin = (friends.c.user_id == id), #condition linking the left side entity
secondaryjoin = (friends.c.friend_id == id),#cond if link right.s ent. with assoc table
backref = db.backref('friends', lazy = 'dynamic'),#how accessed from right
lazy = 'dynamic'
)
#funcitons for bestfriend management
def are_bestfriends(self, user):
return self.is_bestfriend == user
#best friends management
def be_bestfriend(self, user):
if not self.are_bestfriends(user):
self.is_bestfriend = [user]
user.is_bestfriend = [self]
return self
view.py:
#best_freinds
#layout.route('/bestFriend/<name>')
#login_required
def bestFriend(name):
user = Users.query.filter_by(name = name).first()
if user is None:
flash('User %s not found.' % name)
return redirect(url_for('index'))
if user == g.user:
flash('You can\'t Best Friend yourself!')
return redirect(url_for('user', page=1,sortby='normal'))
u = g.user.be_bestfriend(user) #got error here if I remove lazy='dynamic'
if u is None:
flash('Cannot be best Friend ' + name + '.')
return redirect(url_for('user', page=1,sortby='normal'))
db.session.add(u)
db.session.commit()
flash('You are now BestFriend with ' + name + '!')
return redirect(url_for('user', page=1,sortby='normal'))
Like the error message says, you can't use lazy='dynamic' with uselist=False in a relationship; it's only going to load one object anyways, there's no need for dynamic queries against it. Remove lazy='dynamic' from the is_bestfriend relationship.
I am currently using Flask, Flask-SQLAlchemy & Flask-Restless to provide REST routes for a small private AngularJS application. Thus far, I have been able to make/use routes effectively that did not include any relationships.
However, I have a few tables that must have relationships with other tables, which is where my issue is. I get the following Flask error when making a POST to the Flask-Restless Route:
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/usr/local/lib/python2.7/dist-packages/flask_restless/views.py", line 145, in decorator
return func(*args, **kw)
File "/usr/local/lib/python2.7/dist-packages/mimerender.py", line 227, in wrapper
result = target(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/flask/views.py", line 84, in view
return self.dispatch_request(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/flask/views.py", line 149, in dispatch_request
return meth(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/flask_restless/views.py", line 1263, in post
self.session.add(instance)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/scoping.py", line 150, in do
return getattr(self.registry(), name)(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/session.py", line 1492, in add
self._save_or_update_state(state)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/session.py", line 1510, in _save_or_update_state
halt_on=self._contains_state):
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/mapper.py", line 2457, in cascade_iterator
visited_states, halt_on))
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/relationships.py", line 1449, in cascade_iterator
get_all_pending(state, dict_)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/dynamic.py", line 185, in get_all_pending
c.all_items
AttributeError: 'NoneType' object has no attribute '_sa_instance_state'
I think this error has something to do with my model. Here are my current model definitions:
surveyOptions = db.Table('survey_options',
db.Column('survey_id', db.Integer, db.ForeignKey('survey.id')),
db.Column('option_id', db.Integer, db.ForeignKey('option.id')),
db.Column('count', db.Integer)
)
class Survey(db.Model):
id = db.Column(db.Integer, primary_key=True)
category = db.Column(db.String(50))
question = db.Column(db.Text)
startDate = db.Column(db.DateTime)
endDate = db.Column(db.DateTime)
options = db.relationship('Option', secondary=surveyOptions,
backref=db.backref('surveys', lazy='dynamic'), lazy='dynamic')
def __init__(self, category, question, startDate=None, endDate=None, options=None):
self.category = category
self.question = question
if startDate == None:
self.startDate = datetime.utcnow()
if endDate == None:
self.endDate = datetime.utcnow()
self.options.append(options)
class Option(db.Model):
id = db.Column(db.Integer, primary_key=True)
text = db.Column(db.Text)
def __init__(self, text):
self.text = text
...
manager = flask.ext.restless.APIManager(app, flask_sqlalchemy_db=db)
manager.create_api(Survey, methods=['GET','POST','PUT','DELETE'], include_columns=['id','category', 'question', 'startDate','endDate', '_options.id','options.text']);
I would really appreciate some help in isolating the source of this error. I am not sure where to go next with troubleshooting this error.
I can provide more code samples upon request for both the front-end and back-end if needed.
It's because you seem to be appending a list with a list in this section:
def __init__(self, category, question, startDate=None, endDate=None, options=None):
self.category = category
self.question = question
if startDate == None:
self.startDate = datetime.utcnow()
if endDate == None:
self.endDate = datetime.utcnow()
self.options.append(options) # assuming options is a list, this will fail.
The reason that's a problem is simple. If I have my list of options:
foo = ['one', 'two']
and I want to add a few more options to it:
bar = ['three', 'four']
if I foo.append(bar) I get:
foo = ['one', 'two', ['three', 'four']]
Whereas you're actually looking for foo + bar which would give you:
foo = ['one', 'two', 'three', 'four']
When you fix that problem, you're still left with a second weirder problem-- if you don't specify options when you create your Survey object, then, as it stands, your code will try to self.options.append(None) to your object. You need to add a check for that:
if choices: # None or [] will evaluate to False
self.choices += choices
I also notice you do comparisons to None using the == operator, you should really use is to do those comparisons, e.g. if startDate is None:.
I have set up a simple system for adding comments to items in my database using a one-to-many relation (one item can have many comments), but I can't seem to get it to work. It should be simple, I know. It's probably something simple that I've overlooked. I would very much appriciate a second set of eyes on this. Can anyone help?
I have a model defined with SQLAlchemy that looks like this:
class Item(Base):
__tablename__ = 'items' # Parent
id = Column(Integer, primary_key=True)
comments = relationship("Comment", backref='items')
class Comment(Base):
__tablename__ = 'comments' # Child
id = Column(Integer, primary_key=True)
comment_text = Column(Text, nullable=False)
item_id = Column(Integer, ForeignKey('items.id'), nullable=False)
def __init__(self, comment_text, item_id):
self.comment_text = comment_text
self.item_id = item_id
In my view, I do some work, then try to add a comment object:
item = DBSession.query(Item).filter(Item.id == item_id).first()
try:
print('Item id:', item.id, 'Comment text:', comment)
print('Item Comments:', item.comments)
cm = Comment(comment_text=comment,
item_id=item.id)
print('a')
item.comments.append(cm)
#DBSession.add(cm)
print('b')
DBSession.commit()
except:
DBSession.rollback()
print('c')
Note that I tried both item.comments.append(cm) and DBSession.add(cm) with identical results. That's why one of the two is commented out in the above code block. I also tried item.comments.append(Comment(...)) with identical results.
Now, when I try to add a comment, I get a stacktrace, culminating in:
sqlalchemy.exc.ResourceClosedError: This transaction is closed
The whole trace, including the debug prints, look like this:
Item id: 1 Comment text: test
Item Comments: []
a
c
Traceback (most recent call last):
File "C:\Python33\lib\wsgiref\handlers.py", line 137, in run
self.result = application(self.environ, self.start_response)
File "C:\Users\[user]\PYTHON~1.5\lib\site-packages\pyramid\router.py", line 251, in __call__
response = self.invoke_subrequest(request, use_tweens=True)
File "C:\Users\[user]\PYTHON~1.5\lib\site-packages\pyramid\router.py", line 227, in invoke_subrequest
response = handle_request(request)
File "C:\Users\[user]\PYTHON~1.5\lib\site-packages\pyramid\tweens.py", line 21, in excview_tween
response = handler(request)
File "C:\Users\[user]\PYTHON~1.5\lib\site-packages\pyramid_tm\__init__.py", line 82, in tm_tween
reraise(*exc_info)
File "C:\Users\[user]\PYTHON~1.5\lib\site-packages\pyramid_tm\compat.py", line 13, in reraise
raise value
File "C:\Users\[user]\PYTHON~1.5\lib\site-packages\pyramid_tm\__init__.py", line 70, in tm_tween
manager.commit()
File "C:\Users\[user]\PYTHON~1.5\lib\site-packages\transaction\_manager.py", line 111, in commit
return self.get().commit()
File "C:\Users\[user]\PYTHON~1.5\lib\site-packages\transaction\_transaction.py", line 280, in commit
reraise(t, v, tb)
File "C:\Users\[user]\PYTHON~1.5\lib\site-packages\transaction\_compat.py", line 55, in reraise
raise value
File "C:\Users\[user]\PYTHON~1.5\lib\site-packages\transaction\_transaction.py", line 271, in commit
self._commitResources()
File "C:\Users\[user]\PYTHON~1.5\lib\site-packages\transaction\_transaction.py", line 417, in _commitResources
reraise(t, v, tb)
File "C:\Users\[user]\PYTHON~1.5\lib\site-packages\transaction\_compat.py", line 55, in reraise
raise value
File "C:\Users\[user]\PYTHON~1.5\lib\site-packages\transaction\_transaction.py", line 394, in _commitResources
rm.tpc_vote(self)
File "C:\Users\[user]\PYTHON~1.5\lib\site-packages\zope\sqlalchemy\datamanager.py", line 100, in tpc_vote
self.tx.commit()
File "C:\Users\[user]\PYTHON~1.5\lib\site-packages\sqlalchemy\orm\session.py", line 352, in commit
self._assert_active(prepared_ok=True)
File "C:\Users\[user]\PYTHON~1.5\lib\site-packages\sqlalchemy\orm\session.py", line 203, in _assert_active
raise sa_exc.ResourceClosedError(closed_msg)
sqlalchemy.exc.ResourceClosedError: This transaction is closed
Well, turns out the problem was a few corrupt files, not a programming error. Sigh. Well, problem solved. :)