Flask项目引入flask-login时出现ImportError:无法导入url_decode
Flask-Login导入错误解决:ImportError: cannot import name 'url_decode' from 'werkzeug.urls'
我在用Flask构建Web博客应用,引入flask-login库处理用户登录功能时,运行程序触发了ImportError。
项目目录结构
>flask_blog1 >flaskblog >static >templates >__init__.py >forms.py >models.py >routes.py >instance >site.db >venv >requirements.txt >run.py
run.py代码
from flaskblog import app if __name__ == "__main__": app.run(debug=True)
init.py代码
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"] = "5791628bb0b13ce0c676dfde280ba245" app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///site.db" db = SQLAlchemy(app) bcrypt = Bcrypt(app) login_manager = LoginManager(app) from flaskblog import routes
models.py代码
from datetime import datetime # from .extensions import db from flaskblog import db, login_manager from flask_login import UserMixin @login_manager.user_loader def load_user(user_id): return User.query.get(int(user_id)) 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) image_file = db.Column(db.String(20), nullable=False, default="default.jpg") password = db.Column(db.String(60), nullable=False) posts = db.relationship("Post", backref="author", lazy=True) def __repr__(self): return f"User('{self.username}', '{self.email}', '{self.image_file}')" class Post(db.Model): id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(100), nullable=False) date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) content = db.Column(db.Text, nullable=False) user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False) def __repr__(self): return f"Post('{self.title}', '{self.date_posted}')"
routes.py代码
from flask import render_template, flash, redirect, url_for from flaskblog import app, db, bcrypt from flaskblog.forms import RegistrationForm, LoginForm from flaskblog.models import User, Post from flask_login import login_user posts = [ { "author": "Ashutosh Chapagain", "title": "Blog Post 1", "content": "First Post Content", "date_posted": "October 1, 2023", }, { "author": "Ash Dhakal", "title": "Blog Post 2", "content": "Second Post Content", "date_posted": "October 2, 2023", }, ] @app.route("/") @app.route("/home") def home(): return render_template("home.html", posts=posts) @app.route("/about") def about(): return render_template("about.html", title="About") @app.route("/register", methods=["GET", "POST"]) def register(): form = RegistrationForm() if form.validate_on_submit(): hashed_password = bcrypt.generate_password_hash(form.password.data).decode( "utf-8" ) user = User( username=form.username.data, email=form.email.data, password=hashed_password ) db.session.add(user) db.session.commit() flash(f"Your account has been created! You are now able to log in!", "success") return redirect(url_for("login")) return render_template("register.html", title="Register", form=form) @app.route("/login", methods=["GET", "POST"]) def login(): form = LoginForm() if form.validate_on_submit(): user = User.query.filter_by(email=form.email.data).first() if user and bcrypt.check_password_hash(user.password, form.password.data): login_user(user, remember=form.remember.data) return redirect(url_for("home")) else: flash("Login Unsuccessful. Please check email and password", "danger") return render_template("login.html", title="Login", form=form)
forms.py代码
from flask_wtf import FlaskForm from wtforms import StringField, PasswordField, SubmitField, BooleanField from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError from flaskblog.models import User class RegistrationForm(FlaskForm): username = StringField( "Username", validators=[DataRequired(), Length(min=2, max=20)] ) email = StringField("Email", validators=[DataRequired(), Email()]) password = PasswordField("Password", validators=[DataRequired()]) confirm_password = PasswordField( "Confirm Password", validators=[DataRequired(), EqualTo("password")] ) submit = SubmitField("Sign Up") def validate_username(self, username): user = User.query.filter_by(username=username.data).first() if user: raise ValidationError( "That username is taken. Please choose a different one." ) def validate_email(self, email): user = User.query.filter_by(email=email.data).first() if user: raise ValidationError("That email is taken. Please choose a different one.") class LoginForm(FlaskForm): email = StringField("Email", validators=[DataRequired(), Email()]) password = PasswordField("Password", validators=[DataRequired()]) remember = BooleanField("Remember Me") submit = SubmitField("Login")
报错信息
(venv) asu@asu-Lenovo-Legion-5-15ARH05:/media/asu/Data/Projects/flask_blog1$ python3 run.py Traceback (most recent call last): File "/media/asu/Data/Projects/flask_blog1/run.py", line 1, in <module> from flaskblog import app File "/media/asu/Data/Projects/flask_blog1/flaskblog/__init__.py", line 4, in <module> from flask_login import LoginManager File "/media/asu/Data/Projects/flask_blog1/venv/lib/python3.10/site-packages/flask_login/__init__.py", line 12, in <module> from .login_manager import LoginManager File "/media/asu/Data/Projects/flask_blog1/venv/lib/python3.10/site-packages/flask_login/login_manager.py", line 33, in <module> from .utils import _create_identifier File "/media/asu/Data/Projects/flask_blog1/venv/lib/python3.10/site-packages/flask_login/utils.py", line 14, in <module> from werkzeug.urls import url_decode ImportError: cannot import name 'url_decode' from 'werkzeug.urls' (/media/asu/Data/Projects/flask_blog1/venv/lib/python3.10/site-packages/werkzeug/urls.py)
解决办法
这个错误是因为Werkzeug 2.3及以上版本移除了url_decode函数,而当前使用的flask-login版本未适配这个变更。有两种解决方式:
方式一:降低Werkzeug版本到兼容版本
在虚拟环境中执行以下命令,安装兼容的Werkzeug版本:
pip install werkzeug==2.2.3
方式二:升级Flask-Login到最新版本
新版本的Flask-Login已经适配了Werkzeug的API变化,执行升级命令即可:
pip install --upgrade flask-login
内容的提问来源于stack exchange,提问作者Ashutosh Chapagain
相关产品推荐
相关产品推荐

