小能豆

flask admin:sqlalchemy.exc.InterfaceError(错误绑定参数8)

py

我尝试使用下面的方法保存项目的审阅者,并且选择字段显示正确:

# Query the user with Role.id == 4 as reviewer
def reviewer_choices():
    return User.query.join(User.roles).filter(Role.id == 4)

# Build a select field
class ProjectView(sqla.ModelView):
 form_extra_fields = {
    'reviewer': sqla.fields.QuerySelectField(
    label='Reviewer',
    query_factory=reviewer_choices,
 )}

但是,当我尝试保存它时,出现了错误:

InterfaceError: (sqlite3.InterfaceError) Error binding parameter 8 - probably unsupported type. [SQL: u'INSERT INTO project(...reviewer...)VALUES(...<__main__.User object at 0x00000000048E89E8>...)

我注意到审阅者是一个对象,类似于:<__main__.User object at 0x00000000048E89E8>。那么审阅者的正确数据类型是什么,以便我可以将其保存到数据库中?我目前使用:

在项目类中

class Project(db.Model):
   # ...
   reviewer = db.Column(db.Unicode(128)) 
   # ...

在项目表中

CREATE TABLE `project` (
   # ...
   `reviewer1`  TEXT,
   # ...

我也尝试定义 __repr____str__都不起作用:

class User(db.Model, UserMixin):
   id = db.Column(db.Integer, primary_key=True)
   first_name = db.Column(db.String(255))
   # ...
   # ...
   def __repr__(self):
     return self.first_name

class User(db.Model, UserMixin):
   id = db.Column(db.Integer, primary_key=True)
   first_name = db.Column(db.String(255))
   # ...
   # ...
   def __str__(self):
     return self.first_name

阅读 26

收藏
2024-11-07

共1个答案

小能豆

您遇到的问题是 QuerySelectField 返回的是一个 User 对象,而不是可以直接存储到数据库中的类型。要解决这个问题,您可以将 reviewer 字段定义为外键,存储审阅者的 id,而不是整个 User 对象。

以下是具体步骤:

  1. Project 类中使用外键
  2. reviewer 字段定义为 Integer 类型,并将其作为 User 表的外键存储 Userid
  3. 这样可以避免将整个 User 对象存储在 reviewer 字段中,只保存审阅者的唯一标识符。

  4. 调整 QuerySelectField 的处理

  5. 配置 QuerySelectFieldget_pk 方法,使其返回 User 的主键(id),这样表单提交时会返回 id 而不是整个 User 对象。

更新代码如下:

from flask_admin.form.fields import QuerySelectField
from sqlalchemy.orm import backref

# Query the user with Role.id == 4 as reviewer
def reviewer_choices():
    return User.query.join(User.roles).filter(Role.id == 4)

# 更新 Project 模型,使用外键存储 reviewer 的 id
class Project(db.Model):
    # ...
    reviewer_id = db.Column(db.Integer, db.ForeignKey('user.id'))  # 定义为外键
    reviewer = db.relationship('User', backref=backref('projects', lazy=True))  # 建立关系
    # ...

# 使用 Flask-Admin 中的 ModelView 定义表单字段
class ProjectView(sqla.ModelView):
    form_extra_fields = {
        'reviewer': QuerySelectField(
            label='Reviewer',
            query_factory=reviewer_choices,
            get_label='first_name',  # 使用 User 的 first_name 字段显示
            allow_blank=True
        )
    }

解释说明:

  • reviewer_id 字段:在 Project 模型中,我们定义了 reviewer_id 字段来存储 User 的主键(即 id),并通过 db.ForeignKey 设为外键。reviewer 字段则使用 relationship 进行关联,从而可以通过 Project.reviewer 直接访问 User 对象。
  • get_label 参数:在 QuerySelectField 中,get_label='first_name' 表示在选择框中显示 Userfirst_name,而不是显示 User 对象的默认表示形式。
  • get_pk 参数(如果适用):当 QuerySelectField 从表单返回选择项时,获取的是 User 对象的 id,这样可以存储 idreviewer_id 字段中。

注意事项

  • 确保您的 UserProject 模型在数据库中已正确设置外键约束。
  • 如果数据库已存在旧的 project 表,您可能需要迁移数据库或手动修改表结构以反映新的外键设置。
2024-11-07