2016-01-20 2 views
-1

У меня возникла проблема с вышеуказанной ошибкой при создании модели Employee и Photo через форму.Создание моделей через вложенную форму создает DetachedInstanceError

Мой сценарий заключается в том, что я использую Flask-Admin для создания модели Employee с ассоциированным Photo (изображение профиля) с вложенной формой, которую я создал. Когда я создаю одного Сотрудника и связанного с ним фотографии через форму, я не получаю ошибки. Однако, когда я пытаюсь создать другой сотрудник и фото через форму я получаю эту ошибку:

DetachedInstanceError: Instance <Photo at 0x106eca0d0> is not bound to a Session; attribute refresh operation cannot proceed 

Я прочитал документацию по SQLAlchemy о Sessionexpungeexpunge_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 
+0

Пожалуйста, [изменить], чтобы включить [mcve]. Как вы создали Flask-Admin? Где эта фотомодель? Где форма, которую вы создали? Как вы его подаете? Акцент на * минимальный *, вычеркнуть незавершенные поля, представления и т. Д. – davidism

+0

Ошибка относится к тому, что что-то держится за экземпляр через запросы, но контекст сеанса действителен только для одного запроса. Вы не предоставили достаточно кода, чтобы сказать, что это такое, что содержит эту ссылку, или как это исправить. Также было бы полезно добавить полную трассировку. – davidism

+0

@ давидис. Благодарим за помощь с вашими комментариями. Я действительно смог определить, что не так с кодом. Все, что мне было нужно, это изменить параметр конфигурации для Flask-SQLAlchemy –

ответ

-1

я смог преодолеть эту проблему, указав в моей __init__.py следующий код.

db = SQLAlchemy(app,session_options={ 
    'expire_on_commit': False 
}) 
Смежные вопросы