Да, ты прав. В этом причина вашей проблемы. Проблема в различии бэкэндов SQLite и MySQL.
Как вы можете видеть в трассировке стека, он пытается привязать параметр типа FileStorage
и терпит неудачу.
InterfaceError: (sqlite3.InterfaceError) Error binding parameter 0 - probably unsupported type. [SQL: u'SELECT picture.id AS picture_id, picture.name AS picture_name, picture.path AS picture_path \nFROM picture \nWHERE picture.path = ?'] [parameters: (<FileStorage: u'openclipart_hector_gomez_landscape.png' ('image/png')>,)]
Место, где вы хотите поставить точку останова, будет в методе do_execute()
в модуле sqlalchemy.engine.default
.
Серверная часть SQLite - это двоичное расширение, а cursor
происходит от двоичного расширения (_sqlite3.so
). Это двоичное расширение получает параметр типа FileStorage
и пытается преобразовать его в представление SQL, вызывая метод FileStorage.__conform__()
. Но у класса нет такого метода. Вот почему это не удается.
С другой стороны, серверная часть MySQL происходит из чистого модуля Python с именем MySQLdb
. Таким образом, он вызывает метод MySQLdb.cursors.BaseCursor.execute()
, который, в частности, преобразует параметр типа FileStorage
в представление SQL путем вызова db.literal()
, который завершится вызовом FileStorage.__repr__()
. И вы получите следующий запрос:
'SELECT picture.id AS picture_id, picture.name AS picture_name, picture.path AS picture_path
FROM picture
WHERE picture.path = \\'<FileStorage: u\\\\'images.jpeg\\\\' (\\\\'image/jpeg\\\\')>\\''
Неожиданно, правда? Теперь вы не уверены, что он правильно работает с MySQL. Ты? Просто попробуйте создать два изображения с одним и тем же файлом, и вы получите Integrity error. (_mysql_exceptions.IntegrityError) (1062, "Duplicate entry 'images.jpeg' for key 'path'") [SQL: u'INSERT INTO picture (name, path) VALUES (%s, %s)'] [parameters: ('Test', 'images.jpeg')]
вместо значимого сообщения об ошибке.
Почему это работает в примере от Flask-Admin?
Вы устанавливаете ограничение unique
на path
столбец вашей модели. Именно отсюда и возникает сбойный запрос SQL. Прежде чем пытаться вставить новый, он проверяет, существует ли уже изображение с таким же путем в базе данных или нет.
Как исправить
Проблема заключается в ошибке в flask_admin.contrib.sqla.validators.Unique
валидаторе или flask_admin.form.upload.FileUploadField
(они несовместимы). Валидатор должен использовать то же значение, которое было введено в модель методом flask_admin.form.upload.FileUploadField.populate_obj()
, вместо прямой передачи FileStorage
в запрос к базе данных. Просто поднимите проблему на GitHub и укажите этот вопрос.
Я не думаю, что это можно легко исправить в вашем тестовом примере, поскольку это довольно серьезная ошибка в библиотеке, на которую вы полагаетесь. Конечно, при условии, что вы хотите сохранить ограничение unique
на поле path
.
person
Yaroslav Admin
schedule
28.07.2015