Запланируйте SQLAlchemy, чтобы очистить все строки таблицы - PullRequest
0 голосов
/ 03 февраля 2020

Я пытаюсь создать функцию, которая может быть запланирована для удаления всех строк в модели SQLAlchemy.

Я пытаюсь использовать apscheduler для выполнения sh этой задачи. Но я получаю сообщение об ошибке:

sqlalchemy.orm.exc.UnmappedInstanceError: Class 'flask_sqlalchemy.model.DefaultMeta' is not mapped; was a class (app.models.User) supplied where an instance was required?

Я что-то упустил?

Вот мой app/__init__.py:

from flask import Flask
from flask_login import LoginManager
from flask_sqlalchemy import SQLAlchemy
from config import Config

app = Flask(__name__)

db = SQLAlchemy()
login = LoginManager()

app.config.from_object(Config)
db.init_app(app)
login.init_app(app)
login.login_view = 'login'

from app import routes, models

а вот и моя manage.py:

from apscheduler.schedulers.background import BackgroundScheduler
from app import app, db
from flask_migrate import Migrate
from flask_script import Manager
from app.models import User

manager = Manager(app)

migrate = Migrate(app, db)

def clear_data():
    db.session.delete(User)
    print("Deleted User table!")

@manager.command
def run():
    scheduler = BackgroundScheduler()
    scheduler.add_job(clear_data, trigger='interval', seconds=5)
    scheduler.start()
    app.run(debug=True)

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

Также вот моя модель:

from app import db, login
from datetime import datetime
from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash

class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True, unique=True)
    api_token = db.Column(db.String(50), unique=True)
    username = db.Column(db.String(64), index=True, unique=True)
    email = db.Column(db.String(120), index=True, unique=True)
    password_hash = db.Column(db.String(128))
    todos = db.relationship('Todo', backref='owner', lazy='dynamic')

    def __repr__(self):
        return '<models.py {}>'.format(self.username)

    def set_password(self, password):
        self.password_hash = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.password_hash, password)


@login.user_loader
def load_user(id):
    return User.query.get(int(id))


class Todo(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    body = db.Column(db.String(140))
    timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))

    def __repr__(self):
        return '<Todo {}>'.format(self.body)

Ответы [ 2 ]

1 голос
/ 03 февраля 2020

Как указала ваша ошибка, он ожидает экземпляры объекта, и вы вместо этого передали ему класс. Я думаю, что проблема заключается в первой строке в функции clear_data:

db.session.delete(User)

Она ожидала удаления экземпляров пользовательской записи и не знает, как удалить всю таблицу, используя только модель.

Ознакомьтесь с этим ответом о том, как удалить все строки в таблице. Есть несколько способов сделать это, но это может быть наименьшим изменением для вас:

db.session.query(User).delete()

В этом случае вы добавляете шаг SELECT, в котором все записи в таблице, к которым пользователь отображает карту, затем удаляете их.

PS: как указано в связанном ответе, вам нужно на .commit() сеанс, иначе он не будет привязан и откроется после закрытия соединения.

db.session.commit()
0 голосов
/ 03 февраля 2020

Фрагмент кода:

db.session.query(model_name).delete() 
db.session.commit()
...