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

时间:2017-05-13 06:09:29

标签: python flask flask-sqlalchemy flask-admin

此问题困扰了我很长一段时间,我搜索了几天但仍然无法解决问题,包括thisthisthis

下面的代码返回一个查询对象,它在选择字段中正确显示。 但是在提交到数据库时,发生了错误。

  # 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 __ :       错误返回:

  

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 __ :       错误返回:

  

sqlalchemy.exc.InterfaceError InterfaceError :(由于提出的结果)   查询调用autoflush;考虑使用session.no_autoflush块   如果这个刷新过早发生)(sqlite3.InterfaceError)错误   绑定参数8 - 可能不受支持的类型。 [SQL:你' INSERT INTO   项目

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

我目前使用:

在Project类

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

在项目表

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

1 个答案:

答案 0 :(得分:1)

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

QuerySelectField数据属性存储ORM实例,在您的情况下是User模型的实例,而您的reviewer字段是字符串,因此出现错误消息。

您可以创建一个继承的QuerySelectField类并覆盖其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)