2017-05-13 10 views
0

この問題は長い間私を混乱させており、数日間検索しましたが、それでも解決することはできません(thisthis、およびthisなど)。Python Flask:クエリオブジェクトを文字列に変換するには?

以下のコードはクエリオブジェクトを返し、選択フィールドに正しく表示されます。 しかし、データベースに送信するときにエラーが発生しました。

# 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使用:

Projectクラスで

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

プロジェクトテーブルで

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

プロジェクトモデルの定義を表示できますか。 – pjcunningham

+0

@pjcunningham:親切に更新されたポストを見て、ありがとう。 – Samoth

答えて

1

とは対照的に、あなたのプロジェクトのモデルに文字列フィールドとしてreviewerを有する(意図的であると仮定すると、関係である)。

QuerySelectFieldデータプロパティは、reviewerフィールドは、したがって、文字列、エラー・メッセージである一方、あなたの場合には、Userモデルのインスタンスである、ORMインスタンスを格納します。

継承された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

関連する問題