I have a rather complicated set of sqlalchemy models (all are declared using DeclarativeBase, via flask-sqlalchemy db.Model class). The business logic is as follows:
- Each task has one or more questions.
- Each question has one or more options.
- The user can make a presentation containing answers to one or more questions (from one or more tasks)
I prepared an example application to demonstrate the basic functions:
I want my TaskSubmission.task_question_submissions ordered by TaskQuestion.weight , but this does not work, so I will comment the corresponding lines in TaskQuestionSubmission.task_submission :
task_submission = db.relationship( TaskSubmission,
I get this example application with these commands:
./app.py createdb ./app.py createtask ./app.py createsubmission
Then I run debugging commands to see how the materials come out.
./app.py showoldsubmission
Outputs:
Tell us about yourself: Info about Johnny: What is your favourite colour?: Blue Tell us about yourself: Info about Johnny: What is your favourite fruit?: Apple
and
./app.py shownewsubmission
Outputs:
Tell us about yourself: Info about Sarah: What is your favourite colour?: Red Tell us about yourself: Info about Sarah: What is your favourite fruit?: Peach
They are wrong because the question "What is your favorite fruit?" has a lower weight than "What is your favorite color?". He shows "What is your favorite color?" firstly because I first saved TaskQuestion to the database.
If I comment on the lines secondary , secondaryjoin , primaryjoin and order_by , then run the debug commands again, then showoldsubmission works fine:
./app.py showoldsubmission
Outputs:
[Tell us about yourself: Info about Johnny]: What is your favourite fruit?: Apple [Tell us about yourself: Info about Johnny]: What is your favourite colour?: Blue
But:
./app.py shownewsubmission
Outputs:
Traceback (most recent call last): File "./app.py", line 231, in <module> manager.run() File "/wsgi/sqla-rel-test/env/local/lib/python2.7/site-packages/flask_script/__init__.py", line 412, in run result = self.handle(sys.argv[0], sys.argv[1:]) File "/wsgi/sqla-rel-test/env/local/lib/python2.7/site-packages/flask_script/__init__.py", line 383, in handle res = handle(*args, **config) File "/wsgi/sqla-rel-test/env/local/lib/python2.7/site-packages/flask_script/commands.py", line 216, in __call__ return self.run(*args, **kwargs) File "./app.py", line 217, in shownewsubmission question_option=qo) File "<string>", line 4, in __init__ File "/wsgi/sqla-rel-test/env/local/lib/python2.7/site-packages/sqlalchemy/orm/state.py", line 260, in _initialize_instance return manager.original_init(*mixed[1:], **kwargs) File "/wsgi/sqla-rel-test/env/local/lib/python2.7/site-packages/sqlalchemy/ext/declarative/base.py", line 526, in _declarative_constructor setattr(self, k, kwargs[k]) File "/wsgi/sqla-rel-test/env/local/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py", line 226, in __set__ instance_dict(instance), value, None) File "/wsgi/sqla-rel-test/env/local/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py", line 1009, in set lambda adapter, i: adapter.adapt_like_to_iterable(i)) File "/wsgi/sqla-rel-test/env/local/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py", line 1025, in _set_iterable new_values = list(adapter(new_collection, iterable)) File "/wsgi/sqla-rel-test/env/local/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py", line 1009, in <lambda> lambda adapter, i: adapter.adapt_like_to_iterable(i)) File "/wsgi/sqla-rel-test/env/local/lib/python2.7/site-packages/sqlalchemy/orm/collections.py", line 646, in adapt_like_to_iterable given, wanted)) TypeError: <flask_script.commands.Command object at 0x7f4c52967190>: Incompatible collection type: TaskSubmission is not list-like
I tried to pull my hair out, trying to solve this problem - I looked at tons of sqlalchemy documents, forum posts, etc., but I canβt understand.
I am not an expert in sqlalchemy, the material is 'relationship' / 'backref' / 'primaryjoin' / 'secondaryjoin' a little over my head. Anyone who can point out what I'm doing wrong?
Update: I also noticed that after uncommenting the problematic lines, TaskQuestionSubmission.task_submission displays a list instead of a single element. So I tried changing the lines that define the new TaskQuestionSubmission (in the shownewsubmission function) as follows:
tqs = TaskQuestionSubmission(task_submission=[ts], task_question=tq, question_option=qo)
(Note the change: previously task_submission=ts ).
But after doing this, run:
./app.py shownewsubmission
Gives another error:
Traceback (most recent call last): File "./app.py", line 235, in <module> manager.run() File "/wsgi/sqla-rel-test/env/local/lib/python2.7/site-packages/flask_script/__init__.py", line 412, in run result = self.handle(sys.argv[0], sys.argv[1:]) File "/wsgi/sqla-rel-test/env/local/lib/python2.7/site-packages/flask_script/__init__.py", line 383, in handle res = handle(*args, **config) File "/wsgi/sqla-rel-test/env/local/lib/python2.7/site-packages/flask_script/commands.py", line 216, in __call__ return self.run(*args, **kwargs) File "./app.py", line 223, in shownewsubmission tq = t.task_questions[0] File "/wsgi/sqla-rel-test/env/local/lib/python2.7/site-packages/sqlalchemy/orm/dynamic.py", line 254, in __getitem__ sess = self.session File "/wsgi/sqla-rel-test/env/local/lib/python2.7/site-packages/sqlalchemy/orm/dynamic.py", line 237, in session sess.flush() File "/wsgi/sqla-rel-test/env/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 1919, in flush self._flush(objects) File "/wsgi/sqla-rel-test/env/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 2037, in _flush transaction.rollback(_capture_exception=True) File "/wsgi/sqla-rel-test/env/local/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 60, in __exit__ compat.reraise(exc_type, exc_value, exc_tb) File "/wsgi/sqla-rel-test/env/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 2001, in _flush flush_context.execute() File "/wsgi/sqla-rel-test/env/local/lib/python2.7/site-packages/sqlalchemy/orm/unitofwork.py", line 372, in execute rec.execute(self) File "/wsgi/sqla-rel-test/env/local/lib/python2.7/site-packages/sqlalchemy/orm/unitofwork.py", line 481, in execute self.dependency_processor.process_saves(uow, states) File "/wsgi/sqla-rel-test/env/local/lib/python2.7/site-packages/sqlalchemy/orm/dependency.py", line 1051, in process_saves False, uowcommit, "add"): File "/wsgi/sqla-rel-test/env/local/lib/python2.7/site-packages/sqlalchemy/orm/dependency.py", line 1156, in _synchronize self.prop.synchronize_pairs) File "/wsgi/sqla-rel-test/env/local/lib/python2.7/site-packages/sqlalchemy/orm/sync.py", line 84, in populate_dict _raise_col_to_prop(False, source_mapper, l, None, r) File "/wsgi/sqla-rel-test/env/local/lib/python2.7/site-packages/sqlalchemy/orm/sync.py", line 123, in _raise_col_to_prop (source_column, source_mapper, dest_column)) sqlalchemy.orm.exc.UnmappedColumnError: Can't execute sync rule for source column 'task_question.'; mapper 'Mapper|TaskSubmission|task_submission' does not map this column. Try using an explicit `foreign_keys` collection which does not include destination column 'task_question_submission.' (or use a viewonly=True relation).
(Which I find even more perplexing). Thus, it is still not closer to solving this issue.