You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask中forms.py里current_user为NoneType的原因及解决方法

问题:Flask表单定义时current_user为NoneType的原因及解决方法

报错信息

Traceback (most recent call last):
  File "/home/profscrew/Desktop/Progetto_Basi_Dati-master/Codice/__init__.py", line 12, in <module>
    from .artist.routes import artist
  File "/home/profscrew/Desktop/Progetto_Basi_Dati-master/Codice/artist/routes.py", line 6, in <module>
    from Codice.artist.forms import *
  File "/home/profscrew/Desktop/Progetto_Basi_Dati-master/Codice/artist/forms.py", line 28, in <module>
    class SongForm(FlaskForm):
  File "/home/profscrew/Desktop/Progetto_Basi_Dati-master/Codice/artist/forms.py", line 41, in SongForm
    album = SelectField("Album", choices=Album.get_albums(current_user.username), validate_choice=True )
AttributeError: 'NoneType' object has no attribute 'username'

相关代码

forms.py

from flask_wtf import FlaskForm
from wtforms import  StringField, PasswordField,DateField,SubmitField,SelectField,EmailField
from flask_login import current_user
from wtforms.validators import DataRequired, Length, Email, Optional

from Codice.models import *
from Codice.database import *
from Codice.artist.forms import *  # 循环导入,需删除

class SongForm(FlaskForm):
    name = StringField("Name", validators=[DataRequired(),Length(max=40)])
    cover = StringField("Cover", validators=[DataRequired(),Length(max=120)])
    content=StringField("Content", validators=[DataRequired(),Length(max=120)])
    release_date=DateField("Release Date", validators=[DataRequired()])
    genre=SelectField("Genre", choices=Genre.list)
    album = SelectField("Album", choices=Album.get_albums(current_user.username), validate_choice=True )
    
    premium = SelectField("Premium", choices=[' ','The song will be premium','The song will be available to everyone'],
                          validate_choice=True )
    
    submit = SubmitField("Upload")

routes.py

from flask import Blueprint, render_template, redirect, url_for, flash
from flask_login import login_user, logout_user, login_required, current_user

from Codice.models import *
from Codice.database import *
from Codice.artist.forms import *

# Blueprint Configuration
artist = Blueprint('artist', __name__, static_folder='static',
                 template_folder='templates')


@artist.route('/insertsong', methods=['GET','POST'])
@login_required
def insertsong():
    form = SongForm()
    return render_template('insertsong.html', form = form, user = current_user)

models.py(Album类部分)

class Album(Base):
    __tablename__ = 'albums'                   # obbligatorio

    idalbum = Column(Integer, primary_key=True)
    name = Column(String)
    cover = Column(String)
    artist = Column(String, ForeignKey(Artist.username))

    artists = relationship(Artist, backref=backref(
        "albums", cascade="all,  delete, delete-orphan"))

    def get_albums(temp_username):
        albums = Session_artist.query(Album).filter(Album.artist == temp_username).all()
        return albums

原因分析

  1. 表单加载时机问题:SongForm类在应用启动加载模块时就被定义,此时还没有用户请求,flask_login的current_user未被初始化,处于None状态,调用current_user.username自然触发报错。
  2. 循环导入问题:forms.py中from Codice.artist.forms import *属于循环导入,会干扰模块正常加载流程。

解决方法

步骤1:修复循环导入

删除forms.py中的from Codice.artist.forms import *代码,消除循环导入异常。

步骤2:动态填充SelectField选项

不在表单类定义阶段设置choices,先将album字段的choices设为空列表,再在视图函数中(此时current_user已被正确初始化)动态填充选项。同时注意,SelectField的choices需要是**(选项值, 显示文本)**格式的元组列表。

修改后的forms.py

from flask_wtf import FlaskForm
from wtforms import  StringField, PasswordField,DateField,SubmitField,SelectField,EmailField
from wtforms.validators import DataRequired, Length, Email, Optional

from Codice.models import *
from Codice.database import *

class SongForm(FlaskForm):
    name = StringField("Name", validators=[DataRequired(),Length(max=40)])
    cover = StringField("Cover", validators=[DataRequired(),Length(max=120)])
    content=StringField("Content", validators=[DataRequired(),Length(max=120)])
    release_date=DateField("Release Date", validators=[DataRequired()])
    genre=SelectField("Genre", choices=Genre.list)
    # 先设为空列表,后续动态填充
    album = SelectField("Album", choices=[], validate_choice=True )
    
    premium = SelectField("Premium", choices=[' ','The song will be premium','The song will be available to everyone'],
                          validate_choice=True )
    
    submit = SubmitField("Upload")

修改后的routes.py

from flask import Blueprint, render_template, redirect, url_for, flash
from flask_login import login_user, logout_user, login_required, current_user

from Codice.models import *
from Codice.database import *
from Codice.artist.forms import *

# Blueprint Configuration
artist = Blueprint('artist', __name__, static_folder='static',
                 template_folder='templates')


@artist.route('/insertsong', methods=['GET','POST'])
@login_required
def insertsong():
    form = SongForm()
    # 动态填充专辑选项:转换为(主键ID, 专辑名称)的元组列表
    user_albums = Album.get_albums(current_user.username)
    form.album.choices = [(album.idalbum, album.name) for album in user_albums]
    # 可在此添加表单提交逻辑
    return render_template('insertsong.html', form = form, user = current_user)

步骤3(可选):优化Album.get_albums方法

如果希望直接返回符合SelectField要求的格式,可修改get_albums方法:

class Album(Base):
    # 省略其他代码...
    @classmethod
    def get_albums(cls, temp_username):
        albums = Session_artist.query(cls).filter(cls.artist == temp_username).all()
        # 直接返回(值, 文本)的元组列表
        return [(album.idalbum, album.name) for album in albums]

此时视图中可简化为form.album.choices = Album.get_albums(current_user.username)

内容的提问来源于stack exchange,提问作者ProfScrew

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 15:16:01