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)
这个问题困扰了我很久,找了几天还是没解决,包括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)