2013-07-26 2 views
7

Я пытаюсь иметь поле выбора, заполненное результатами запроса sqlalchemy в форме фляжки.Как использовать QuerySelectField в колбе?

Вот код:

def possible_book(): 
    return Book.query.with_entities(Book.id).all() 

class AuthorForm(Form): 
    familyname = TextField('familyname', [validators.Required()]) 
    firstname = TextField('firstname', [validators.Required()]) 
    book_list = QuerySelectField('book_list',query_factory=possible_book,get_label='title',allow_blank=True) 

Это шаблон:

<form action="" method="post" name="edit_author" enctype="multipart/form-data"> 
    {{form.hidden_tag()}} 
    <p>Veuillez donner son prénom (obligatoire) : {{form.firstname(value=author.firstname)}}</p> 
    <p>Nom de famille (obligatoire) : {{form.familyname(value=author.familyname)}}</p> 
    <p>Livre : {{form.book_list}}</p> 

    <p><input type="submit" value="Envoyer"></p> 
</form> 

Вид:

@app.route('/edit_author/<number>', methods = ['GET', 'POST']) 
    def edit_author(number): 
    if number == 'new': 
     author = [] 
    else: 
     author = Author.query.filter_by(id = number).first() 
    form = AuthorForm() 
    if form.validate_on_submit(): 
     a = Author(firstname= form.firstname.data, familyname= form.familyname.data) 
     a.books = form.book_list.data 

     db.session.add(a) 
     db.session.commit() 
    return redirect('/admin') 
return render_template('edit_author.html', form = form, author = author) 

Модель (вставили только ассоциативная таблица и таблица автор, большая часть колонки не может быть и речи)

author_book = db.Table('author_book', 
    db.Column('author', db.Integer, db.ForeignKey('author.id')), 
    db.Column('book', db.Integer, db.ForeignKey('book.id')) 
) 

class Author(db.Model): 
    id = db.Column(db.Integer, primary_key = True) 
    firstname = db.Column(db.String(64), index = True) 
    familyname = db.Column(db.String(120), index = True) 
    website = db.Column(db.String(120)) 
    dateofbirth = db.Column(db.DateTime) 
    placeofbirth = db.Column(db.String(120)) 
    nationality = db.Column(db.String(120)) 
    biography = db.Column(db.Text) 
    photo = db.Column(db.String(120)) 
    books = db.relationship('Book', secondary=author_book,backref=db.backref('author', lazy='dynamic')) 

В настоящее время я получаю эту ошибку:

UnmappedInstanceError: Class 'sqlalchemy.util._collections.KeyedTuple' is not mapped 

То, что я действительно хочу, чтобы выбрать поле показать имя автора и его номер, и возвращать число автора в приложение (к функции под названием «add_author " на голове).

спасибо.

+0

протестировали вы ваш метод possible_book() и убедитесь, что он работает как задумано? – codegeek

+0

Я не знаю, что вы подразумеваете под «проверенным». Возможная книга - это просто запрос, и он работает, без проблем. Он возвращает весь список книг (или авторов, если вы используете другую сторону). Но я уверен, что ему нужно что-то большее, чтобы его интерпретировать по форме или шаблону или что-то еще. Вот что мне интересно! Это то, что я не понимаю: как заставить его работать с формой? – 22decembre

ответ

6

У вас есть две проблемы:

  1. Как Шон Виейра отметил в своем ответе, query_factory обратного вызова должна возвращать запрос, а не результаты.

  2. Обратный вызов query_factory должен возвращать полные объекты, в ваших книгах, а не книжные ids. Я считаю, что QuerySelectField должен пытаться использовать результаты запроса так, как если бы они были сопоставленными объектами, но идентификаторы (возвращаемые как экземпляры KeyedTuple) не являются.

Я думаю, что это правильный способ кодирования функцию обратного вызова:

def possible_book(): 
    return Book.query 
+0

, просто используя Book.query, он, кажется, нашел начало ответа! Теперь у меня есть поле выбора! – 22decembre

+0

Дорогой @ Мигель, можете ли вы, пожалуйста, помочь мне с этим [sqlalchemy.exc.InterfaceError in Flask] (http: // stackoverflow.com/questions/24732871/sqlalchemy-exc-interfaceerror-in-flask). Я использовал ** QuerySelectField **, и он вызывает ошибку. Я не знаю, как это исправить. спасибо – Max

3

Одна из возможных проблем заключается в том, что wtforms.ext.sqlalchemy.fields.QuerySelectField ожидает объект запроса SQLAlchemy, а не материализованный список. Просто удалите all() вызова из possible_book возвращения вернуть unmaterialized запрос WTForms:

def possible_book(): 
    return Book.query.with_entities(Book.id) 
+0

Я попробовал, и, похоже, это не решило проблему. У меня все еще такая же ошибка. Я думаю, что я должен поместить каждый результат запроса в кортеж (разговор debbugger о сопоставленном кортеже ...), но я не знаю, как и как правильно использовать его после! – 22decembre