首页 > 解决方案 > 导入flask-SQLAlchemy模型时出现AttributeError

问题描述

我正在按照教程构建基于 JWT 的身份验证系统。

应用程序.py:

from flask import Flask
from flask_restful import Api
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SECRET_KEY'] = 'd0cad49580952003e6ae01499c7bb190a4b4f9a5babd866f47064707f7b78506'

api = Api(app)
db = SQLAlchemy(app)


@app.before_first_request
def create_tables():
    db.create_all()


import resources, models

api.add_resource(resources.UserRegistration, '/registration')


if __name__ == '__main__':
    app.run()

模型.py:

from app import db


class UserModel(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    password = db.Column(db.String(150), nullable=False)
    email = db.Column(db.String(100), unique=True, nullable=False)

    def __init__(self, name, password, email):
        self.name = name
        self.password = password
        self.email = email

    @classmethod
    def find_by_username(cls, username):
        return cls.query.filter_by(username=username).first()

    def save_to_db(self):
        db.session.add(self)
        db.session.commit()

资源.py:

from flask_restful import Resource, reqparse
from models import UserModel


class UserRegistration(Resource):
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('name', help='This field cannot be blank', required=True)
        parser.add_argument('email', help='This field cannot be blank', required=True)
        parser.add_argument('password', help='This field cannot be blank', required=True)

        data = parser.parse_args()

        if UserModel.find_by_username(data['name']):
            return {'message': 'User {} already exists'.format(data['name'])}

        new_user = UserModel(
            name=data['name'],
            password=data['password'],
            email=data['email']
        )
        try:
            new_user.save_to_db()
            return {
                'status': 'User {} was created'.format(data['username'])}

        except:
            return {'message': 'Something went wrong'}, 500

当我运行 app.py 时,我收到以下错误:

Traceback (most recent call last):
  File "G:\python\PycharmProjects\vumonic\app.py", line 19, in <module>
    import resources, models
  File "G:\python\PycharmProjects\vumonic\resources.py", line 2, in <module>
    from models import UserModel
  File "G:\python\PycharmProjects\vumonic\models.py", line 1, in <module>
    from app import db
  File "G:\python\PycharmProjects\vumonic\app.py", line 21, in <module>
    api.add_resource(resources.UserRegistration, '/registration')
AttributeError: module 'resources' has no attribute 'UserRegistration'

from models import UserModel当我从 resources.py中删除时,此错误消失。

我无法弄清楚错误的原因。

我正在使用 Flask==1.1.2、Flask-SQLAlchemy==2.4.4 和 Flask-RESTful==0.3.8

这是我第一次开发 API,因此将不胜感激。

标签: pythonflaskflask-sqlalchemyflask-restful

解决方案


您正面临循环导入问题。

当 Python 导入一个模块时,它会检查模块注册表以查看该模块是否已被导入。如果模块已经注册,Python 会使用缓存中的现有对象。模块注册表是一个已初始化并按模块名称索引的模块表。可以通过 访问该表sys.modules

如果没有注册,Python 会找到该模块,必要时初始化它,然后在新模块的命名空间中执行它。

要了解有关循环导入的更多信息,您可以阅读文章:

https://stackabuse.com/python-circular-imports/

https://www.stefaanlippens.net/circular-imports-type-hints-python.html

Miguel Grinberg 的本教程是救生员 https://www.youtube.com/watch?v=NH-8oLHUyDc&t=3205s


推荐阅读