flask-rest-jsonapi icon indicating copy to clipboard operation
flask-rest-jsonapi copied to clipboard

AttributeError: 'UUID' object has no attribute '_sa_instance_state'

Open Krasnov8953 opened this issue 6 years ago • 3 comments
trafficstars

I have this error while i'm trying to update or create element with some relation. Here's my logs output

Traceback (most recent call last):
 File "/usr/local/lib/python3.5/dist-packages/flask/app.py", line 1994, in __call__
   return self.wsgi_app(environ, start_response)
 File "/usr/local/lib/python3.5/dist-packages/flask/app.py", line 1985, in wsgi_app
   response = self.handle_exception(e)
 File "/usr/local/lib/python3.5/dist-packages/flask_restful/__init__.py", line 269, in error_router
   return original_handler(e)
 File "/usr/local/lib/python3.5/dist-packages/flask/app.py", line 1540, in handle_exception
   reraise(exc_type, exc_value, tb)
 File "/usr/local/lib/python3.5/dist-packages/flask/_compat.py", line 33, in reraise
   raise value
 File "/usr/local/lib/python3.5/dist-packages/flask/app.py", line 1982, in wsgi_app
   response = self.full_dispatch_request()
 File "/usr/local/lib/python3.5/dist-packages/flask/app.py", line 1614, in full_dispatch_request
   rv = self.handle_user_exception(e)
 File "/usr/local/lib/python3.5/dist-packages/flask_restful/__init__.py", line 269, in error_router
   return original_handler(e)
 File "/usr/local/lib/python3.5/dist-packages/flask/app.py", line 1517, in handle_user_exception
   reraise(exc_type, exc_value, tb)
 File "/usr/local/lib/python3.5/dist-packages/flask/_compat.py", line 33, in reraise
   raise value
 File "/usr/local/lib/python3.5/dist-packages/flask/app.py", line 1612, in full_dispatch_request
   rv = self.dispatch_request()
 File "/usr/local/lib/python3.5/dist-packages/flask/app.py", line 1598, in dispatch_request
   return self.view_functions[rule.endpoint](**req.view_args)
 File "/usr/local/lib/python3.5/dist-packages/flask_rest_jsonapi/decorators.py", line 30, in wrapped_f
   response = f(*args, **kwargs)
 File "/usr/local/lib/python3.5/dist-packages/flask_rest_jsonapi/decorators.py", line 22, in wrapped_f
   return f(*args, **kwargs)
 File "/usr/local/lib/python3.5/dist-packages/flask/views.py", line 84, in view
   return self.dispatch_request(*args, **kwargs)
 File "/usr/local/lib/python3.5/dist-packages/flask_rest_jsonapi/resource.py", line 126, in dispatch_request
   resp = meth(*args, **kwargs)
 File "/usr/local/lib/python3.5/dist-packages/flask_rest_jsonapi/decorators.py", line 81, in wrapped_f
   return f(self, *args, **kwargs)
 File "/usr/local/lib/python3.5/dist-packages/flask_rest_jsonapi/resource.py", line 271, in patch
   self.data_layer.update_and_save_item(item, data, **kwargs)
 File "/usr/local/lib/python3.5/dist-packages/flask_rest_jsonapi/data_layers/alchemy.py", line 105, in update_and_save_item
   setattr(item, field, data[field])
 File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/orm/attributes.py", line 261, in __set__
   instance_state(instance), instance_dict(instance), value, None
 File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/orm/attributes.py", line 1240, in set
   new_values, old_collection, new_collection, initiator=evt
 File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/orm/collections.py", line 790, in bulk_replace
   appender(member, _sa_initiator=initiator)
 File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/orm/collections.py", line 1092, in append
   item = __set(self, item, _sa_initiator)
 File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/orm/collections.py", line 1064, in __set
   item = executor.fire_append_event(item, _sa_initiator)
 File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/orm/collections.py", line 707, in fire_append_event
   self.owner_state, self.owner_state.dict, item, initiator
 File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/orm/attributes.py", line 1091, in fire_append_event
   value = fn(state, value, initiator or self._append_token)
 File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/orm/unitofwork.py", line 45, in append
   item_state = attributes.instance_state(item)
AttributeError: 'UUID' object has no attribute '_sa_instance_state'```

UserModel

    """Base user model class."""

    __tablename__ = 'users'

    id = Column(UUID,
                server_default=text('gen_random_uuid()'),
                primary_key=True)

    email = Column(VARCHAR(120), unique=True)
    email_new = Column(VARCHAR(120))
    email_code = Column(UUID)

    email_password_code = Column(UUID)
    email_password_at = Column(TIMESTAMP)

    password = Column(VARCHAR(40))
    role = Column(VARCHAR(16), default=ROLE_ANON)
    tokens = relationship('Token',
                          back_populates='user',
                          cascade="all, delete-orphan")
    seasons = relationship('Season', secondary=girl_to_season)
    # Many to many relationships
    cities = relationship("City", secondary=moder_to_city)

Data Layer

class ModerAdminDataLayer(SqlalchemyDataLayer):
    """Moder Admin DB data layer."""

    def get_base_query(self, **view_kwargs):
        """Base query for moder."""
        base_query = self.session.query(User).filter_by(role=ROLE_MODER)
        return base_query

class ModerAdminDetail(ResourceDetail):
    """Moder Admin API details."""

    class Meta:
        """Detail meta."""

        data_layer = {
            'cls': ModerAdminDataLayer,
            'kwargs': {
                'session': flask_db.session,
                'model': User,
                'id_field': 'id',
                'url_param_name': 'moder_id'
            },
            'before_update_instance': before_update_instance
        }
    schema_patch_kwargs = {"partial": True}
    resource_type = 'moder'
    schema = {
        'cls': ModerAdminSchema
    }```

Schema

    """Moder admin [de]serialization schema."""

    id = fields.UUID(dump_only=True)
    first_name = make_string_field(80)
    last_name = make_string_field(80)

    email = make_string_field(120, [Email()])
    password = fields.String(load_only=True)

    is_banned = fields.Boolean()

    created_at = fields.DateTime(dump_only=True)

    cities = fields.Relationship(
        type_='cities',
        schema='CitySchema',
        many=True,
        related_url='/api_admin/moders/{moder_id}/cities/',
        related_url_kwargs={'moder_id': '<id>'}
    )
    moderation_cities = fields.String(dump_only=True)

    class Meta:
        """Schema meta."""

        type_ = 'moder'```

I use: python 3.5 SQLAlchemy 1.2.17 Flask-REST-JSONAPI 0.5.1

Krasnov8953 avatar Feb 11 '19 12:02 Krasnov8953

I have same problem too

zombiegit avatar Feb 15 '19 08:02 zombiegit

It was resolved when I downgraded marshmallow-jsonapi to version 0.11.0 🎉

Krasnov8953 avatar Feb 15 '19 13:02 Krasnov8953

@Krasnov8953, I'm seeing the same thing in 0.11.0 also. Did you make any other changes? Are you still running back at flask-rest-jsonapi 0.5.1?

Using Python 3.7.2, flask-rest-jsonapi is at 0.26.0 marshmallow-jsonapi at either latest or 0.11.0. Seeing the same issue with multiple versions of marshmallow-jsonapi.

Have also tried setting schema field type to either uuid or as string. When setting the view to a string, also tried setting the value with either str(uuid) or uuid.hex and receiving same error. Didn't ever get uuid.int to save.

Did get it to work with the latest pypi versions of both packages and Model/View fields of String types and saving as integers as string (i.e. str(uuid4().int) ), hex as string (i.e. str(uuid4().hex) ) did not work

Some of that may be the backend db, but didn't take time to finish finding the root cause.

ghost avatar Mar 07 '19 02:03 ghost