У меня возникла проблема с вышеуказанной ошибкой при создании модели Employee и Photo через форму.Создание моделей через вложенную форму создает DetachedInstanceError
Мой сценарий заключается в том, что я использую Flask-Admin
для создания модели Employee
с ассоциированным Photo
(изображение профиля) с вложенной формой, которую я создал. Когда я создаю одного Сотрудника и связанного с ним фотографии через форму, я не получаю ошибки. Однако, когда я пытаюсь создать другой сотрудник и фото через форму я получаю эту ошибку:
DetachedInstanceError: Instance <Photo at 0x106eca0d0> is not bound to a Session; attribute refresh operation cannot proceed
Я прочитал документацию по SQLAlchemy о Session
expunge
expunge_all()
flush
и каскады, но я до сих пор не в состоянии получить этот для правильной работы. Я все равно получаю ту же ошибку, и я не уверен, что еще попробовать.
----------- EDIT (код и полная ошибка трассировки) ----------------
Вот код формы
forms.py
class PhotoForm(Form):
-------conditional logic that determines s3 config or not -------
image = S3ImageUploadField(base_path=app.config['UPLOAD_FOLDER'],
namegen = photo_name_generator,
storage_type = '',
storage_type_field = '',
bucket_name = '',
bucket_name_field = '',
access_key_id = '',
access_key_secret = '',
static_root_parent = app.config['UPLOAD_FOLDER'])
DEPARTMENTS = ['place a series of tuples indicating department choices']
class EmployeeForm(Form):
name = StringField('Full Name', validators=[DataRequired()])
title = StringField('Job Title', validators=[DataRequired()])
email = StringField('Company Email', validators=[DataRequired()])
department = SelectField('Department', choices=DEPARTMENTS)
photo = FormField(PhotoForm)
Вот код модели
models.py
#-----photo_name_generator grabs the filename and changes it to the employees name------
def photo_name_generator(obj,file_data):
parts = path.splitext(file_data.filename)
return secure_filename(str(obj.employee[0].name) + str(parts[1]))
class Photo(db.Model):
__tablename__ = 'photos'
id = db.Column(db.Integer, primary_key=True)
image = db.Column(db.String(200))
storage_type_field = db.Column(db.String(255), default='')
bucket_name_field = db.Column(db.String(255), default='')
def __init__(self, image='', storage_type_field='', bucket_name_field=''):
self.image = image
self.storage_type_field = storage_type_field
self.bucket_name_field = bucket_name_field
def __repr__(self):
return '<Photo %r>' % self.image
class Employee(db.Model):
__tablename__ = 'employees'
id = db.Column(db.Integer, primary_key=True)
photo_id = db.Column(db.Integer, db.ForeignKey(Photo.id))
photo = db.relationship("Photo", backref='employee', cascade='all, delete-orphan', single_parent=True, uselist=False)
name = db.Column(db.String(200))
title = db.Column(db.String(200))
email = db.Column(db.String(200))
department = db.Column(db.String(200))
def __init__(self, name='', title='', email='', department='', photo=Photo()):
self.name = name
self.title = title
self.email = email
self.department = department
self.photo = photo
def __repr__(self):
return '<User %r>' % self.name
Вот код ADMIN
admin.py
class EmployeeView(ModelView):
form = EmployeeForm
def _list_thumbnail(view, context, model, name):
return Markup('<img height="100" width="100" src="%s">' % url_for('static',
filename= 'images/' + model.photo.image))
column_formatters = {
'photo': _list_thumbnail
}
form_extra_fields = {
'photo': ImageUploadField('Image', base_path=app.config['UPLOAD_FOLDER'])
}
def on_model_delete(self,model):
os.remove(app.config['UPLOAD_FOLDER'] + model.photo.image)
def is_accessible(self):
return flask_login.current_user.is_authenticated
admin.add_view(EmployeeView(Employee, db.session))
ошибка трассировки:
sqlalchemy.orm.exc.DetachedInstanceError
DetachedInstanceError: Instance <Photo at 0x1060d50d0> is not bound to a Session; attribute refresh operation cannot proceed
Traceback (most recent call last)
File "/Users/drubio/Desktop/blackduckflock/venv/lib/python2.7/site-packages/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "/Users/drubio/Desktop/blackduckflock/venv/lib/python2.7/site-packages/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/Users/drubio/Desktop/blackduckflock/venv/lib/python2.7/site-packages/flask/app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Users/drubio/Desktop/blackduckflock/venv/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/Users/drubio/Desktop/blackduckflock/venv/lib/python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/drubio/Desktop/blackduckflock/venv/lib/python2.7/site-packages/flask/app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Users/drubio/Desktop/blackduckflock/venv/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/drubio/Desktop/blackduckflock/venv/lib/python2.7/site-packages/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/drubio/Desktop/blackduckflock/venv/lib/python2.7/site-packages/flask_admin/base.py", line 68, in inner
return self._run_view(f, *args, **kwargs)
File "/Users/drubio/Desktop/blackduckflock/venv/lib/python2.7/site-packages/flask_admin/base.py", line 359, in _run_view
return fn(self, *args, **kwargs)
File "/Users/drubio/Desktop/blackduckflock/venv/lib/python2.7/site-packages/flask_admin/model/base.py", line 1674, in create_view
model = self.create_model(form)
File "/Users/drubio/Desktop/blackduckflock/venv/lib/python2.7/site-packages/flask_admin/contrib/sqla/view.py", line 1004, in create_model
if not self.handle_view_exception(ex):
File "/Users/drubio/Desktop/blackduckflock/venv/lib/python2.7/site-packages/flask_admin/contrib/sqla/view.py", line 987, in handle_view_exception
return super(ModelView, self).handle_view_exception(exc)
File "/Users/drubio/Desktop/blackduckflock/venv/lib/python2.7/site-packages/flask_admin/contrib/sqla/view.py", line 999, in create_model
form.populate_obj(model)
File "/Users/drubio/Desktop/blackduckflock/venv/lib/python2.7/site-packages/wtforms/form.py", line 96, in populate_obj
field.populate_obj(obj, name)
File "/Users/drubio/Desktop/blackduckflock/venv/lib/python2.7/site-packages/wtforms/fields/core.py", line 807, in populate_obj
self.form.populate_obj(candidate)
File "/Users/drubio/Desktop/blackduckflock/venv/lib/python2.7/site-packages/wtforms/form.py", line 96, in populate_obj
field.populate_obj(obj, name)
File "/Users/drubio/Desktop/blackduckflock/venv/lib/python2.7/site-packages/flask_admin_s3_upload.py", line 58, in populate_obj
field = getattr(obj, name, None)
File "/Users/drubio/Desktop/blackduckflock/venv/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py", line 237, in __get__
return self.impl.get(instance_state(instance), dict_)
File "/Users/drubio/Desktop/blackduckflock/venv/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py", line 573, in get
value = state._load_expired(state, passive)
File "/Users/drubio/Desktop/blackduckflock/venv/lib/python2.7/site-packages/sqlalchemy/orm/state.py", line 480, in _load_expired
self.manager.deferred_scalar_loader(self, toload)
File "/Users/drubio/Desktop/blackduckflock/venv/lib/python2.7/site-packages/sqlalchemy/orm/loading.py", line 610, in load_scalar_attributes
(state_str(state)))
DetachedInstanceError: Instance <Photo at 0x1060d50d0> is not bound to a Session; attribute refresh operation cannot proceed
Пожалуйста, [изменить], чтобы включить [mcve]. Как вы создали Flask-Admin? Где эта фотомодель? Где форма, которую вы создали? Как вы его подаете? Акцент на * минимальный *, вычеркнуть незавершенные поля, представления и т. Д. – davidism
Ошибка относится к тому, что что-то держится за экземпляр через запросы, но контекст сеанса действителен только для одного запроса. Вы не предоставили достаточно кода, чтобы сказать, что это такое, что содержит эту ссылку, или как это исправить. Также было бы полезно добавить полную трассировку. – davidism
@ давидис. Благодарим за помощь с вашими комментариями. Я действительно смог определить, что не так с кодом. Все, что мне было нужно, это изменить параметр конфигурации для Flask-SQLAlchemy –