#python #sqlite #flask #sqlalchemy #flask-sqlalchemy
#python #sqlite #flask #sqlalchemy #flask-sqlalchemy
Вопрос:
Здравствуйте, я борюсь с этой ошибкой уже несколько недель. В моем приложении python / flask мне нужно сохранить pw в таблице db user в SQLite с помощью SQLAlchemy. Кажется, что таблица создана правильно, когда я проверяю sqlite> .schema, там есть столбец pwd. Когда я запускаю приложение, оно возвращает ошибку, в которой говорится, что столбец pwd не существует (см. Ошибку ниже). Я несколько раз пытался удалить таблицу, пытаясь создать новую базу данных, но ничего, я думаю, что таблица создана правильно, но в коде должно быть что-то не так? Также может быть испорчена база данных, но я так не думаю.
Здесь я создаю таблицу и определяю класс User в соответствии с официальной документацией SQLAlchemy
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from sqlalchemy import *
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///data-users.sqlite'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer(), primary_key = True, autoincrement=True)
username = db.Column(db.String(64), unique = True)
pwd = db.Column(db.String())
def __repr__(self):
return '<User %r>' % self.username
Здесь я сохраняю пользовательские данные в таблице
from store_user_db import User, db
db.create_all()
DICP_FTP_DESTINATION_PSW=self.submit_pwd()
user = User(id=001,username="ita_itf",pwd=DICP_FTP_DESTINATION_PSW)
db.session.add(user)
db.session.commit()
Это ошибка:
sqlalchemy.exc.OperationalError
OperationalError: (sqlite3.OperationalError) table user has no column named pwd
[SQL: INSERT INTO user (id, username, pwd) VALUES (?, ?, ?)]
[parameters: (1, 'ita_itf', <read-only buffer for 0x7efe495709f0, size -1, offset 0 at 0x7.....
Комментарии:
1. Как насчет вызова
db.create_all()
вашего определения класса модели пользователя? И я не думаю, что вам нужно добавлятьmeta
иusertable
2. db.create_all() ничего не сделает, таблица уже создана в части метаданных(), если я удалю это, таблица не будет создана, насколько я понимаю, код в классе User предназначен только для определения класса user, а не для создания таблицы, для создания таблицы вы должны использовать функцию Table()
3. Поэтому, если я удалю код #CREATE TABLE с метаданными и т.д., Я повторно инициализирую базу данных, удаляю таблицу, затем запускаю приложение, сообщение об ошибке то же самое. В основном, как я и думал, не пытается сохранить данные в созданной мной таблице, а сохраняет их в несуществующей таблице.
4. Это необычно для использования
meta
иusertable
таким образом, как вы используете их в чистых приложениях flask-sqlalchemy . Возможно, было бы полезно установитьSQLALCHEMY_ECHO
значениеTrue
в вашей конфигурации, чтобы мы могли видеть команды, которые отправляются в базу данных.5. Хорошо, тогда предположим, что я не буду использовать meta, как мне создать новую таблицу в БД? что это за код?
Ответ №1:
У меня нет большого опыта работы с flask и SQLAlchemy, но вот пример приложения, которое работает для меня. Определения моделей взяты из документации и добавлена тестовая модель во время выполнения, чтобы проверить, способна ли она по-прежнему создавать новые таблицы, и это произошло.
Если у вас большое приложение, я бы предпочел использовать flask-migrate
библиотеку, которая может создавать версионные миграции из ваших моделей для создания / изменения ваших таблиц.
from datetime import datetime
from flask import Flask, request, flash, url_for, redirect, json
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
db = SQLAlchemy(app)
class User(db.Model):
__tablename__ = "user"
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
def __repr__(self):
return '<User %r>' % self.username
class Category(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), nullable=False)
def __repr__(self):
return '<Category %r>' % self.name
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(80), nullable=False)
body = db.Column(db.Text, nullable=False)
pub_date = db.Column(db.DateTime, nullable=False,
default=datetime.utcnow)
category_id = db.Column(db.Integer, db.ForeignKey('category.id'),
nullable=False)
category = db.relationship('Category',
backref=db.backref('posts', lazy=True))
def __repr__(self):
return '<Post %r>' % self.title
class Test(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), nullable=False)
def __repr__(self):
return '<Test %r>' % self.name
def insertAdminUser():
admin = User(username='admin', email='admin@example.com')
db.session.add(admin)
db.session.commit()
@app.route('/insert-admin', methods = ['GET'])
def insertAdmin():
insertAdminUser()
return app.response_class(
response=json.dumps({
"message": "inserted"
}),
mimetype='application/json'
)
if __name__ == '__main__':
db.create_all()
app.run(debug = True)
Комментарии:
1. хорошо, я вижу, поэтому я замечаю, что основное отличие заключается в том, что в коде, который вы разместили в def в классе User, он возвращает что-то, в то время как мой инициализация def ничего не возвращает, основываясь на коде, который я написал, как вы думаете, моя функция def пользовательского класса должна что-то возвращать? В моем случае я должен передать идентификатор, пользователя и пароль, поэтому должен вернуть их все? как мне написать это на практике? Я совсем новичок в python
2. В python
__repr__
возвращает объектное представление класса и не требуется. И__init__
(конструктор) — это метод, вызываемый при создании нового экземпляра и не обязанный ничего возвращать. Вы можете определить / переопределить свой собственный__init__
метод. Я думаю, вам следует сначала узнать о ООП Python.3. Здесь довольно хорошо объяснено, кажется таким простым, но таким образом это не создаст никакой таблицы в моей базе данных! flask-sqlalchemy.palletsprojects.com/en/2.x/quickstart
4. Я знаю, что о init действительно я говорил о repr
5. Если я сделаю это, как в статье, это даже не создаст файл db