sqlalchemy.exc.DataError: (psycopg2.errors.InvalidTextRepresentation) invalid input syntax for type integer: "B1"

sqlalchemy.exc.DataError: (psycopg2.errors.InvalidTextRepresentation) invalid input syntax for type integer: "B1"

我正在尝试使用 ID 在我的 Flask 应用程序上登录管理员,当我注册时它完美地接受了输入,但是当从数据库 (postgresql) 获取值时它显示 "DataError" 我已将输入作为 HTML 形式的字母数字

这是我的代码:

在 model.py 我已经为数据库编写代码来创建列

model.py

class Admin(UserMixin, db.Model):
    id = db.Column(db.String(1000), primary_key=True )
    name = db.Column(db.String(1000))
    email = db.Column(db.String(100), unique=True)
    password = db.Column(db.String(100))
    timestamp = db.Column(db.DateTime)

在此 auth.py 中,我为 POST 注册和登录方法编写了代码

auth.py

@auth.route('/admin')
def admin():
    return render_template('admin.html')


@auth.route('/admin', methods=['POST'])
def admin_post():
    id = request.form.get('id')
    password = request.form.get('password')
    remember = True if request.form.get('remember') else False

admins = Admin.query.filter_by(id=id).first()

# check if the user actually exists
# take the user-supplied password, hash it, and compare it to the hashed password in the database
if not admins or not check_password_hash(admins.password, password):
    flash('Please check your login details and try again.')
    # if the user doesn't exist or password is wrong, reload the page
    return redirect(url_for('auth.admin'))

# if the above check passes, then we know the user has the right credentials
login_user(admins, remember=remember)
return redirect(url_for('main.adminOP'))


 @auth.route('/admin-signup')
 def adminsignup():
     return render_template('admin-signup.html')


 @auth.route('/admin-signup', methods=['POST'])
 def adminsignup_post():
     id = request.form.get('id')
     email = request.form.get('email')
     name = request.form.get('name')
     password = request.form.get('password')
     timestamp = datetime.now()

# if this returns a admin, then the email already exists in database
admins = Admin.query.filter_by(email=email).first()

if admins:  # if a user is found, we want to redirect back to signup page so user can try again
    flash('Email address already exists')
    return redirect(url_for('auth.adminsignup'))

# create a new user with the form data. Hash the password so the plaintext version isn't saved.
new_admin = Admin(id=id, email=email, name=name,
                  password=generate_password_hash(password, method='sha256'), timestamp=timestamp)

# add the new user to the database
db.session.add(new_admin)
db.session.commit()

return redirect(url_for('auth.admin'))

回溯捕获到的错误是:

sqlalchemy.exc.DataError: (psycopg2.errors.InvalidTextRepresentation) invalid input syntax for type 
integer: "B1"
LINE 3: WHERE person.id = 'B1'
                          ^

[SQL: SELECT person.id AS person_id, person.email AS person_email, person.password AS person_password, 
person.name AS person_name, person.timestamp AS person_timestamp
FROM person
WHERE person.id = %(pk_1)s]
[parameters: {'pk_1': 'B1'}]
(Background on this error at: http://sqlalche.me/e/14/9h9h)

这里B1是id

admin-signup.html

正如我之前所说,我在输入字段中使用了字母数字

{% extends "base.html" %}

{% block content %}
<div class="column is-4 is-offset-4">
    <h3 class="title has-text-info">Sign Up</h3>
    <div class="box">
        {% with messages = get_flashed_messages() %}
        {% if messages %}
        <div class="notification is-danger">
            {{ messages[0] }}. Go to <a href="{{ url_for('auth.admin') }}">login page</a>.
        </div>
        {% endif %}
        {% endwith %}
        <form method="POST" action="/admin-signup">
            <div class="field">
                <div class="control has-icons-left has-icons-right">
                    <input class="input is-large" type="text" name="id" placeholder="Your ID" autofocus="" pattern="[a-zA-Z0-9]+"><span
                        class="icon is-small is-left">
                        
                    </span>
                    <small> Remember: ID is you employee number </small>
                </div>
            </div>
            <div class="field">
                <div class="control has-icons-left has-icons-right">
                    <input class="input is-large" type="email" aria-required="true" name="email" placeholder="Email"
                        autofocus=""><span class="icon is-small is-left">
                        
                    </span>
                </div>
            </div>

            <div class="field">
                <div class="control has-icons-left has-icons-right">
                    <input class="input is-large" type="text" aria-required="true" name="name" placeholder="Name"
                        autofocus=""><span class="icon is-small is-left">
                        
                    </span>
                </div>
            </div>

            <div class="field">
                <div class="control has-icons-left has-icons-right">
                    <input class="input is-large" type="password" aria-required="true" name="password"
                        placeholder="Password"><span class="icon is-small is-left">
                        
                    </span>
                </div>
            </div>

            <button class="button is-block is-info is-large is-fullwidth">Sign Up</button>
        </form>
    </div>
</div>
{% endblock %}

admin.html

{% extends "base.html" %}

{% block content %}
<div class="column is-4 is-offset-4">
    <h3 class="title has-text-info">Admin Login</h3>
    <div class="box">
        {% with messages = get_flashed_messages() %}
        {% if messages %}
        <div class="notification is-danger">
            {{ messages[0] }}
        </div>
        {% endif %}
        {% endwith %}
        <form method="POST" action="/admin">
            <div class="field">
                <div class="control has-icons-left has-icons-right">
                    <input class="input is-large" type="text" name="id" placeholder="Your ID" autofocus="" required pattern="[a-zA-Z0-9]+"><span
                        class="icon is-small is-left">
                        
                    </span>
                    <small> HINT: ID is you employee number </small>
                </div>
            </div>

            <div class="field">
                <div class="control has-icons-left has-icons-right">
                    <input class="input is-large" type="password" name="password" placeholder="Your Password"><span
                        class="icon is-small is-left">
                        
                    </span>
                </div>
            </div>
            <div class="field">
                <label class="checkbox">
                    <input type="checkbox">
                    Remember me
                </label>
            </div>
            <button class="button is-block is-info is-large is-fullwidth">Login</button>
        </form>
    </div>
</div>
{% endblock %}

编辑代码后,我在调试时遇到了同样的错误

这是人物模型

class person(UserMixin, db.Model):
    # primary keys are required by SQLAlchemy
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(100), unique=True)
    password = db.Column(db.String(100))
    name = db.Column(db.String(1000))
    timestamp = db.Column(db.DateTime)

问题是您的 person 模型中的列 id 是整数,而不是字符串。您的 load_user 函数查询 person 模型提供的键 B1,无法转换为整数。

如果您打算查询您的 Admin 模型并且 根据登录者查询您的 person 模型,您应该在您的登录期间的用户会话,并在 load_user 函数中检索它。查看 了解更多详情。

但是如果你需要区别对待你的用户(User#1 是管理员,而 User#2 不是),你真的应该考虑在你的模型中使用布尔标志,像这样:

class User(UserMixin, db.Model):
    id = db.Column(db.String(1000), primary_key=True )
    name = db.Column(db.String(1000))
    # ...
    is_admin = db.Column(db.Boolean)

你真的应该避免让两个用户的模型使用不同类型的密钥,随着时间的推移它会变得非常混乱。

如果您的 Flask 应用程序倾向于增长并拥有多种类型的用户,您应该考虑采用 'user roles' 的概念。查看 Flask-Principal 为此。

旧答案

问题可能是因为您的模型和数据库不同步。在某些时候,您可能有 id = db.Column(db.Integer, primary_key=True) 然后 运行 db.create_all() 的开发过程,然后将 id 更改为 id = db.Column(db.String(1000), primary_key=True).

简单来说,Flask认为id是string,而PostgreSQL确定是int。可以肯定的是,您可以使用以下方法检查 table person 的 DDL:

pg_dump -U your_user your_database -t person --schema-only

请注意 flask/flask-sqlalchemy 不会自动迁移,更改模型后您应该重新创建数据库或手动应用更改(选择由您决定)。