Python Flask:如何将查询对象转换为字符串?

Python Flask: How to convert a query object to string?

这个问题困扰了我很久,找了几天还是没解决,包括this, this, and this.

下面的代码 returns 是一个查询对象,它在 select 字段中正确显示。 但是在提交到数据库时,出现了错误。

  # 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(
    query_factory=reviewer_choices,
  )}

我试图定义 __repr____str__ 以便将其转换为字符串但是徒劳无功,有没有其他方法可以将查询对象转换为字符串?提前致谢。

1. __repr__: 错误 returns:

sqlalchemy.exc.InterfaceError InterfaceError:

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

2。 __str__: 错误 returns:

sqlalchemy.exc.InterfaceError InterfaceError: (raised as a result of Query-invoked autoflush; consider using a session.no_autoflush block if this flush is occurring prematurely) (sqlite3.InterfaceError) Error binding parameter 8 - probably unsupported type. [SQL: u'INSERT INTO project

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

我目前使用:

项目中class

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

项目中table

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

假设在您的项目模型中将 reviewer 作为字符串字段是有意的(而不是关系)。

一个QuerySelectField数据属性存储一个ORM实例,在你的例子中是一个User模型的实例,而你的reviewer字段是一个字符串,因此错误信息。

您可以创建一个继承的 QuerySelectField class 并覆盖其 populate_obj 方法以将选定的 User 实例转换为您选择的字符串,例如

class ProjectQuerySelectField(QuerySelectField):

    def populate_obj(self, obj, name):
        # obj is the current model being edited/created
        # name is the field name - 'reviewer' in this instance
        # self.data is the user instance selected in the form
        setattr(obj, name, str(self.data))

请注意使用 str 函数来获取所选用户实例的字符串表示形式。

请参阅下面的独立示例应用程序。导航至 http://127.0.0.1:5000/admin/project/ 以查看所选用户如何转换为字符串。

from flask import Flask
from flask_admin.contrib.sqla import ModelView
from flask_admin.contrib.sqla.fields import QuerySelectField
from flask_security import Security, SQLAlchemyUserDatastore, RoleMixin, UserMixin
from flask_sqlalchemy import SQLAlchemy


from flask_admin import Admin
# Create application
app = Flask(__name__)

# Create dummy secrey key so we can use sessions
app.config['SECRET_KEY'] = '123456790'

# Create in-memory database
app.config['DATABASE_FILE'] = 'sample_db.sqlite'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + app.config['DATABASE_FILE']
app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app)


# Flask views
@app.route('/')
def index():
    return '<a href="/admin/">Click me to get to Admin!</a>'


# Define models
roles_users = db.Table('roles_users',
        db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
        db.Column('role_id', db.Integer(), db.ForeignKey('role.id')))


class Role(db.Model, RoleMixin):

    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(255), unique=True)
    description = db.Column(db.String(255))

    def __str__(self):
        return unicode(self).encode('utf-8')

    def __unicode__(self):
        return self.name


class User(db.Model, UserMixin):

    id = db.Column(db.Integer, primary_key=True)
    first_name = db.Column(db.String(255))
    last_name = db.Column(db.String(255))
    email = db.Column(db.String(254), unique=True)

    roles = db.relationship('Role', secondary=roles_users, backref=db.backref('users', lazy='dynamic'))

    def __str__(self):
        return unicode(self).encode('utf-8')

    def __unicode__(self):
        return ', '.join(filter(None, [self.first_name, self.last_name, self.email]))


class Project(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255))
    reviewer = db.Column(db.Unicode(128))

    def __str__(self):
        return unicode(self).encode('utf-8')

    def __unicode__(self):
        return self.name


# Setup Flask-Security
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore)


class UserView(ModelView):
    column_list = ['first_name', 'last_name', 'email', 'roles']
    form_columns = ['first_name', 'last_name', 'email', 'roles']


class RoleView(ModelView):
    form_columns = ['name', 'description']


def reviewer_choices():
    # return User.query.join(User.roles).filter(Role.id == 4)
    return User.query.join(User.roles).filter(Role.name == u'Reviewer')


class ProjectQuerySelectField(QuerySelectField):

    def populate_obj(self, obj, name):
        setattr(obj, name, str(self.data))


class ProjectView(ModelView):

    form_extra_fields = {
        'reviewer': ProjectQuerySelectField(
            query_factory=reviewer_choices,
        )}


admin = Admin(app, template_mode="bootstrap3")
admin.add_view(UserView(User, db.session))
admin.add_view(RoleView(Role, db.session))
admin.add_view(ProjectView(Project, db.session))


def build_sample_db():
    db.drop_all()
    db.create_all()

    # Reviewer will have id : 4 and will have index 3 in _roles list
    _roles = []
    for _name in ['Admin', 'Editor', 'Reader', 'Reviewer']:
        _role = Role(name=_name)
        _roles.append(_role)

    db.session.add_all(_roles)

    # get the "Reviewer" Role
    _reviewer_role = _roles[3]

    # Give Paul and Serge "Reviewer" role
    _user_1 = User(first_name="Paul", last_name="Cunningham", email="paul@example.com", roles=[_reviewer_role])
    _user_2 = User(first_name="Luke", last_name="Brown", email="luke@example.com")
    _user_3 = User(first_name="Serge", last_name="Koval", email="serge@example.com", roles=[_reviewer_role])

    db.session.add_all([_user_1, _user_2, _user_3])

    db.session.commit()


if __name__ == '__main__':
    build_sample_db()
    app.run(port=5000, debug=True)