He estado aprendiendo el marco de la aplicación web del matraz y me siento bastante cómodo con él. Previamente construí una aplicación fácil de hacer que funcionó perfectamente. Estaba trabajando en el mismo proyecto, pero tratando de implementarlo usando TDD. Encontré un error con la base de datos que nunca antes había visto y no sé cómo solucionarlo.
Cuando examino mi código, no puedo ver ningún problema. También parece idéntico al código del proyecto de trabajo, por lo que realmente no sé qué estoy haciendo mal.
Aquí están los errores:
(env) PS C:\coding-projects\task-master-tdd> flask shell Python 3.8.5 (tags/v3.8.5:580fbb0, Jul 20 2020, 15:43:08) [MSC v.1926 32 bit (Intel)] on win32 App: project [development] Instance: C:\coding-projects\task-master-tdd\instance >>> from project import db >>> db Traceback (most recent call last): File "<console>", line 1, in <module> File "c:\coding-projects\task-master-tdd\env\lib\site-packages\flask_sqlalchemy\__init__.py", line 1060, in __repr__ self.engine.url if self.app or current_app else None File "c:\coding-projects\task-master-tdd\env\lib\site-packages\flask_sqlalchemy\__init__.py", line 943, in engine return self.get_engine() File "c:\coding-projects\task-master-tdd\env\lib\site-packages\flask_sqlalchemy\__init__.py", line 962, in get_engine return connector.get_engine() File "c:\coding-projects\task-master-tdd\env\lib\site-packages\flask_sqlalchemy\__init__.py", line 555, in get_engine options = self.get_options(sa_url, echo) File "c:\coding-projects\task-master-tdd\env\lib\site-packages\flask_sqlalchemy\__init__.py", line 570, in get_options self._sa.apply_driver_hacks(self._app, sa_url, options) File "c:\coding-projects\task-master-tdd\env\lib\site-packages\flask_sqlalchemy\__init__.py", line 914, in apply_driver_hacks sa_url.database = os.path.join(app.root_path, sa_url.database) AttributeError: can't set attribute >>>mi archivo config.py:
import os # load the environment variables from the .env file from dotenv import load_dotenv load_dotenv() # Determine the folder of the top-level directory of this project BASEDIR = os.path.abspath(os.path.dirname(__file__)) class Config: FLASK_ENV = 'development' TESTING = False DEBUG = False SECRET_KEY = os.getenv('SECRET_KEY', default='A very terrible secret key.') SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URL', default=f"sqlite:///{os.path.join(BASEDIR, 'instance', 'app.db')}") SQLALCHEMY_TRACK_MODIFICATIONS = False class DevelopmentConfig(Config): DEBUG = True class TestingConfig(Config): TESTING = True SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URL', default=f"sqlite:///{os.path.join(BASEDIR, 'instance', 'test.db')}") class ProductionConfig(Config): FLASK_ENV = 'production'mi modelo de usuario:
from project import db, login_manager from flask_login import UserMixin from werkzeug.security import generate_password_hash, check_password_hash class User(db.Model, UserMixin): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String, unique=True) hashed_password = db.Column(db.String) def __init__(self, username, password): self.username = username self.hashed_password = generate_password_hash(password) def is_password_valid(self, password): return check_password_hash(self.hashed_password, password) def __repr__(self): return '<User {}>'.format(self.id) @login_manager.user_loader def load_user(user_id): return User.query.get(int(user_id))Acabo de enfrentar exactamente el mismo error. Resulta que tenía instalada la biblioteca Flask-SQLAlchemy incorrecta. Lo instalé usando conda en lugar de pip, y conda instaló el adecuado para mi sistema operativo y entorno.
conda install Flask-SQLAlchemyResolví este problema anulando apply_driver_hacks en la clase SQLAlchemy. En este nuevo método, eliminé esta línea: sa_url.database = os.path.join(app.root_path, sa_url.database) . Copié el resto del método.
class MySQLAlchemy(SQLAlchemy): def apply_driver_hacks(self, app, sa_url, options): ...El método se puede encontrar aquí . La solución que describí solo debería ser temporal. El problema podría solucionarse en las versiones más nuevas de matraz-sqlalchemy.
Si experimenta esto, actualizar Flask-SQLAlchemy a >= 2.5 debería resolver el problema según https://github.com/pallets/flask-sqlalchemy/issues/910#issuecomment-802098285 .
Fijar SQLAlchemy a ~1.3 ya no debería ser necesario.
Me encontré con este problema un poco antes, pero creo que me he dado cuenta de lo que está pasando.
SQLAlchemy se instala automáticamente como una dependencia para Flask-SQLAlchemy y su última versión (1.4.0) presenta el siguiente cambio importante:
El objeto URL ahora es una tupla con nombre inmutable. Para modificar un objeto de URL, utilice el método URL.set() para producir un nuevo objeto de URL.
Pude solucionar este problema simplemente instalando la versión anterior de SQL Alchemy (1.3.23).
Vuelva a comprobar que este problema le afecta ejecutando
pip freezeDebería encontrar que la versión actual de sqlalchemy es 1.4.0 . Encontré que la solución más rápida por ahora es volver manualmente a una versión anterior de sqlalchemy:
pip install SQLAlchemy==1.3.23Si acaba de volver a la versión anterior y funciona, ahora es un buen momento para anclar sus versiones:
pip freeze > requirements.txtPude arreglar esto fijando mi versión de sql-alchemy a menos de 1.4.0 . Ejemplos similares se enumeran arriba. A continuación se muestran los pasos que hice para resolver esto hasta que ocurra un parche.
Congele sus paquetes
pip freeze > requirements.txt Actualice su SQLAlchemy en sus requisitos.txt
SQLAlchemy<1.4.0Reinstalar los paquetes
pip install -r requirements.txtPara obtener más información sobre cómo hacer esto, consulte la documentación de pip: https://pip.pypa.io/en/stable/
Confirmando la respuesta de npburns224/SuperShoot : Actualizar Flask-SQLAlchemy (y por lo tanto su dependencia SQLAlchemy ) a la última versión fue el truco para mí.
pip install --upgrade flask-sqlalchemy Ahora estoy ejecutando Flask-SQLAlchemy 2.5.1 y SQLAlchemy 1.4.3 con éxito.