2017-05-13 17 views
0

이 문제로 인해 오랫동안 혼란스러워졌습니다. 며칠 동안 검색했지만 여전히 해결할 수 없습니다 (this, thisthis 포함).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 사용 :

를 프로젝트 클래스

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