2017-05-13 53 views
0

这个问题困扰了我很长一段时间,我搜索了几天,但仍不能解决它,包括this,this,和thisPython烧瓶:如何将查询对象转换为字符串?

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

# 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: (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 

I电流LY使用:

在项目类

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

在项目表

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

您能否显示您的项目模型定义。 – pjcunningham

+0

@pjcunningham:很高兴看到更新后的帖子,非常感谢。 – Samoth

回答

1

假设在你的项目模型有reviewer作为串场是故意的(相对于是一种关系)。

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

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

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="[email protected]", roles=[_reviewer_role]) 
    _user_2 = User(first_name="Luke", last_name="Brown", email="[email protected]") 
    _user_3 = User(first_name="Serge", last_name="Koval", email="[email protected]", 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) 
+0

@ pjcunningham:非常感谢您的回复,并且您的应用运行良好。但是,对于我的应用程序,出现了以下错误:'sqlalchemy.exc.InterfaceError InterfaceError :(由于查询调用的autoflush而引发;如果此刷新过早发生,请考虑使用session.no_autoflush块)(sqlite3.InterfaceError)错误绑定参数8 - 可能不受支持的类型。'我可以看到评论者在下拉按钮中正确显示,但保存错误时发生。 – Samoth