miguelgrinberg / flasky

Companion code to my O'Reilly book "Flask Web Development", second edition.
MIT License
8.52k stars 4.21k forks source link

self.follow(self) causes unittest error #279

Closed butflame closed 7 years ago

butflame commented 7 years ago

HI miguel,sorry to bother. It's about a func in User.init to make users follow themselves,the codes in your book was like below, self.follow(self)

but in your repository: self.followed.append(Follow(followed=self))

And that in your book causes unittest error: sqlalchemy.orm.exc.DetachedInstanceError: Parent instance <User at 0x7fb90d3e49b0> is not bound to a Session, and no contextual session is established; lazy load operation of attribute 'followed' cannot proceed

I don't understand what caused the error, how it affects the result of unittest, and what's the differences between the two above.

Hope u can reply this, thx

miguelgrinberg commented 7 years ago

Do you have the complete stack trace of the error please?

butflame commented 7 years ago

Sorry for late. The complete trace is too long because there are 17 errors out of 21 tests. Here's part of the trace about 1 test:

`ERROR: test_valid_reset_token (test_user_model.UserModelTestCase)

Traceback (most recent call last): File "c:\FLAPP\tests\test_user_model.py", line 71, in test_valid_reset_token u = User(password='cat') File "", line 4, in init File "c:\flaskenv\lib\site-packages\sqlalchemy\orm\state.py", line 414, in _in itialize_instance manager.dispatch.init_failure(self, args, kwargs) File "c:\flaskenv\lib\site-packages\sqlalchemy\util\langhelpers.py", line 60, in exit compat.reraise(exc_type, exc_value, exc_tb) File "c:\flaskenv\lib\site-packages\sqlalchemy\util\compat.py", line 187, in r eraise raise value File "c:\flaskenv\lib\site-packages\sqlalchemy\orm\state.py", line 411, in _in itialize_instance return manager.original_init(*mixed[1:], *kwargs) File "c:\FLAPP\app\models.py", line 124, in init self.follow(self) File "c:\FLAPP\app\models.py", line 213, in follow if not self.is_following(user): File "c:\FLAPP\app\models.py", line 232, in is_following followed_id=user.id).first() is not None File "c:\flaskenv\lib\site-packages\sqlalchemy\orm\query.py", line 1558, in fi lterby return self.filter(sql.and(clauses)) File "", line 2, in filter File "c:\flaskenv\lib\site-packages\sqlalchemy\orm\base.py", line 198, in gene rate self = args[0].clone() File "c:\flaskenv\lib\site-packages\sqlalchemy\orm\dynamic.py", line 278, in clone orm_util.instance_str(instance), self.attr.key)) sqlalchemy.orm.exc.DetachedInstanceError: Parent instance <User at 0x3f2eeb0> is not bound to a Session, and no contextual session is established; lazy load ope ration of attribute 'followed' cannot proceed


Ran 21 tests in 21.628s

FAILED (errors=17)`

Other errors are quiet similar, the only difference was the instance of a certain test in line1 in traceback,.

miguelgrinberg commented 7 years ago

Great. So you can see in the stack trace that the error occurs when you do self.followed.filter_by(...) in line 232 of models.py. This line instructs the database to do a join operation between two tables, to find if the user you want to follow was already added. The problem is that self isn't in the database yet, so it does not have an id assigned, which makes the join operation impossible.

The way I implemented that initial self follow is by just doing self.folllowed.append() which does not require any database joins or searches.

You could probably make self.follow(self) work in the constructor if you add a check to skip the is_following() check when the instance does not have an id still.

I will make sure this is fixed for the new edition of the book!

butflame commented 7 years ago

OK, I got it. I should concentrate more. Thank u very much, and I'll close the issue.

By the way, in styles.css ,I think the 'post-content' should be replaced by 'post-body', and the 'post-author' should have a 'margin-left:48px'. Both in ur repository.