Closed cisko3000 closed 7 years ago
This error is probably because there is some error when the post is stored on this line just above the one you are quoting:
pid = _store_form_data(form, storage, current_user, post)
Does this always occur, or only once? If there was more info to be able to help out.
It always occurs on the live website. If I copy the sqlite database to my dev environment, it works fine. If there was a way to use the debugger that comes with flask, I would be able to figure this out quick. Do you think it's because of my tables? I don't have a user table. I have the tables: post, tag, tag_posts, user_posts. I don't know why this would be a problem, both live and dev flask-blogging extensions are same version.
Right now I'm updating my blog posts by creating the new post on test and copying the database over to live.
If you have time, I can provide you with any information you need.
Well, I am trying to understand what is different about your production? What is your database setup? Do you have a User's model as described in the docs?
Looks like both are the same. Does production being HTTPS matter?
I think the HTTPS case would need to be correctly handled. Some pages that discuss are here:
http://stackoverflow.com/questions/14810795/flask-url-for-generating-http-url-instead-of-https http://flask.pocoo.org/snippets/35/
Let me take a look. If you get this working, I will take a pull request. :)
I am getting this error in my dev env, though without any https involved. I run on a port different from 80.
I'm also encountering this problem. Flask-Blogging worked for me using the example. However, when I tried to switch to Flask-Sqlalchemy to handle user authentication, that's when I started encountering this error (the list of blog posts also does not work, though that seems to be caused by the fact that I can't create any posts).
Perhaps this is not an actual bug and the problem could be cleared up by separating out the code for Flask-Sqlalchemy a little more in the docs or maybe providing a working example which uses it?
@scottkleinman Flask-Sqlalchemy isn't used for authentication directly. I think u mean Flask-Login/Flask-Security? I protect parts of my blog with flask-security and can share some code if this is your problem.
@Speedy1991 Yes, I realise that was a little unclear. I actually meant using Flask-Sqlalchemy for the database. I tried to implement it as I was integrating the login system here. Everything went well until I got the error mentioned in this issue, and I had also identified pid = _store_form_data(form, storage, current_user, post)
as the likely place where the problem was occurring. So I thought it was worth asking if it was Flask-Sqlalchemy issue.
I haven't tried using using Flask-Security, but, if you have working code to share, that might help me see where I'm going wrong. Thanks!
I don't see anywhere flask-blogging in your link - im not sure if this problem depends on this repository. Anyway, setting up a user loader is as easy as this:
@blog_engine.user_loader
def load_user(user_id):
return db.session.query(User).get(user_id)
If you have acces to _currentuser u can return this user too.
I tried to add flask-blogging to the code there. I'm pasting below the way I did it. Lines with #
after them are my additions to try to get the blog engine to work. There's probably some redundancy or conflict here in the way that I am implementing the blog_engine to work with flask_sqlalchemy. If I comment out @login_manager.user_loader
and uncomment @blog_engine.user_loader
, I get an error saying "No user_loader has been installed for this LoginManager".
from flask_blogging import SQLAStorage, BloggingEngine #
from sqlalchemy import create_engine, MetaData #
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
...
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/blog.db'
db = SQLAlchemy(app)
...
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(15), unique=True)
email = db.Column(db.String(50), unique=True)
password = db.Column(db.String(80))
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'
db.create_all()
metadata = MetaData() #
storage = SQLAStorage(db=db, metadata=metadata) #
blog_engine = BloggingEngine() #
blog_engine.init_app(app, storage) #
@login_manager.user_loader
def load_user(user_id):
return User.query.get(user_id)
#@blog_engine.user_loader #
#def load_user(user_id): #
# return db.session.query(User).get(user_id) #
U need both methods
@login_manager.user_loader
Loads the user for for _loginmanager
@blog_engine.user_loader
Loads (not loged in) users for the blog (e.g. seeing the author names)
Just copy
User.query.get(user_id)
to your 2nd loader and it should work (i didnt test it)
I thought that would work too, but no luck. I'm guessing it is because there are two load_user
functions (?), but I'm not sure how to get around that.
well i just tested it, my gist is running just fine. Check it out here Edit: You can access /editor after /login and get a redirect to login if u try to access after you visited /logout
That helps a lot. I got it working for my site. Thanks! It turns out that I had a dashboard with the @login_required
decorator, which was causing problems. So I imported current_user
from flask_login, and {% if current_user.is_authenticated %}
works in the template, so I can use that.
My login function is now something like:
@app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user:
# hashed password check to be added here.
login_user(user, remember=form.remember.data)
return redirect(url_for('blog'))
return render_template('blogging/login.html', form=form)
Now I'm encountering a couple of other problems which I think are related. When I create a blog post and view it (using the page.html
template), the username following "Posted by" is something like '<__main__.User object at 0x0000000003D77E10>'
. Also, when I use the index.html
template to view all blog posts, I get an error because the meta
object has not been passed to the template. If I comment out all the references to meta
, I don't get any posts displayed. I've tried to figure out how to import MetaData
and insert meta = MetaData()
in my app.py
file, but nothing seems to work. Any chance you could show how that works in your gist?
For the blog to have a readable display name, the User class must implement either the
get_name
method or the__str__
method.
@scottkleinman Just to give you a sense of what is going on:
load_user
decorator accomplishes. You could modify your original code as follows to get it to work.@login_manager.user_loader
def load_user_flask_login(user_id):
return User.query.get(user_id)
@blog_engine.user_loader #
def load_user_flask_blogging(user_id): #
return User.query.get(user_id)
Now the extensions know how to load the user, but they don't know what the user should be called. That is accomplished by setting the __str__
method or get_name
method for the User
object mentioned above.
The metadata is sort of like a blueprint for the database. It contains information on what the database schemas look like. However since Flask-SQLAlchemy and Flask-Blogging share the same database, you have to share the same metadata between them. When you don't pass a metadata, Flask-SQLAlchemy creates one for you. So you can try the following
...
metadata = MetaData() #
db = SQLAlchemy(app, metadata=metadata)
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(15), unique=True)
email = db.Column(db.String(50), unique=True)
password = db.Column(db.String(80))
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'
storage = SQLAStorage(db=db, metadata=metadata) #
...
# the create_all after all the database hooks.
Thanks, @gouthambs. That did the trick! Just to clarify for anyone trying to follow this exchange, it appears that I accidentally deleted the following from the Quickstart Example:
def get_name(self):
return "Paul Dirac" # typically the user's name
Once I restored that, the "Posted by" name rendered correctly in the template.
I'm not sure if any of this solves the endpoint building problem that originally prompted this issue, but it worked for me.
Was the original issue ever resolved? I am getting the exact same error under very similar conditions to @cisko3000.
Hi, sorry, i am not sure. i gave up on using flask blogging, currently learning wagtail cms on django
Francisco Barcena http://www.LosAngelesCoder.com
On Aug 5, 2017 9:10 PM, "dtrimarco" notifications@github.com wrote:
Was the original issue ever resolved? I am getting the exact same error under very similar conditions to @cisko3000 https://github.com/cisko3000 .
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/gouthambs/Flask-Blogging/issues/83#issuecomment-320484498, or mute the thread https://github.com/notifications/unsubscribe-auth/AHlAS3TRTVteYxZsVSYFiq5Dm-zWzMwAks5sVTyagaJpZM4LJyxn .
@dtrimarco If you can post a sample of your code, I might be able to provide some feedback. It is unclear why some experience this issue, while others don't. I have a site up on HTTPS as well, and haven't run into this issue.
To me it seems like a combination of better documentation + improved error messsages is required.
Hi, not sure if this is a flask-blogging issue or something else. I am getting the following when making a post on production server. In development, I am not able to recreate the problem. I managed to debug a bit on production (it is a pain because I have to restart everything for a new printing of value). I found out that
post_id
isNone
right before url_for() is called at line 248:If it makes a difference, I just made my website use HTTPS a while ago. Though I don't remember if this problem existed before that. I think it did.