collerek/ormar

select_related with ManyToMany through

Opened this issue · 1 comments

Describe the bug
Trying to query a ManyToMany through relationship and getting this error:

ormar.exceptions.RelationshipInstanceError: Relationship error - ForeignKey EffortResource is of type <class 'int'> while <class 'weakref.ProxyType'> passed as a parameter.

after running await EffortStep.objects.select_related("users").all().

Models:

class User(PublicIdMixin, ormar.Model):
    id = ormar.Integer(primary_key=True)

    class Meta(BaseMeta):
        tablename = "users"

class EffortStepUser(ormar.Model):
    id = ormar.Integer(primary_key=True)

    class Meta(BaseMeta):
        tablename = "effort_step_x_user"

class EffortStep(PublicIdMixin, DateFieldsMixin, TenantAwareModel, ormar.Model):
    id = ormar.Integer(primary_key=True)
    users = ormar.ManyToMany(
        User,
        through=EffortStepUser,
        through_relation_name="step_id",
        through_reverse_relation_name="user_id",
    )

    class Meta(BaseMeta):
        tablename = "effort_step"

class EffortResource(DateFieldsMixin, TenantAwareModel, ormar.Model):
    id = ormar.Integer(primary_key=True)
    step: EffortStep = ormar.ForeignKey(EffortStep, name="step_id", nullable=False)

    class Meta(BaseMeta):
        tablename = "effort_resource"

Full traceback

Traceback (most recent call last):
  File "/.venvs/core/lib/python3.11/site-packages/uvicorn/protocols/http/httptools_impl.py", line 419, in run_asgi
    result = await app(  # type: ignore[func-returns-value]
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/.venvs/core/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__
    return await self.app(scope, receive, send)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/.venvs/core/lib/python3.11/site-packages/fastapi/applications.py", line 270, in __call__
    await super().__call__(scope, receive, send)
  File "/venvs/core/lib/python3.11/site-packages/starlette/applications.py", line 124, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/.venvs/core/lib/python3.11/site-packages/starlette/middleware/errors.py", line 184, in __call__
    raise exc
  File "/.venvs/core/lib/python3.11/site-packages/starlette/middleware/errors.py", line 162, in __call__
    await self.app(scope, receive, _send)
  File "/.venvs/core/lib/python3.11/site-packages/starlette/middleware/cors.py", line 92, in __call__
    await self.simple_response(scope, receive, send, request_headers=headers)
  File "/.venvs/core/lib/python3.11/site-packages/starlette/middleware/cors.py", line 147, in simple_response
    await self.app(scope, receive, send)
  File "/.venvs/core/lib/python3.11/site-packages/starlette/middleware/exceptions.py", line 79, in __call__
    raise exc
  File "/.venvs/core/lib/python3.11/site-packages/starlette/middleware/exceptions.py", line 68, in __call__
    await self.app(scope, receive, sender)
  File "/.venvs/core/lib/python3.11/site-packages/fastapi/middleware/asyncexitstack.py", line 21, in __call__
    raise e
  File "/.venvs/core/lib/python3.11/site-packages/fastapi/middleware/asyncexitstack.py", line 18, in __call__
    await self.app(scope, receive, send)
  File "/.venvs/core/lib/python3.11/site-packages/starlette/routing.py", line 706, in __call__
    await route.handle(scope, receive, send)
  File "/.venvs/core/lib/python3.11/site-packages/starlette/routing.py", line 276, in handle
    await self.app(scope, receive, send)
  File "/.venvs/core/lib/python3.11/site-packages/starlette/routing.py", line 66, in app
    response = await func(request)
               ^^^^^^^^^^^^^^^^^^^
  File "/.venvs/core/lib/python3.11/site-packages/fastapi/routing.py", line 235, in app
    raw_response = await run_endpoint_function(
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/.venvs/core/lib/python3.11/site-packages/fastapi/routing.py", line 161, in run_endpoint_function
    return await dependant.call(**values)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/src/efforts/router.py", line 95, in add_effort_collaborators
    return await service.add_step_zero_collaborators(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/src/efforts/service.py", line 165, in add_step_zero_collaborators
    await EffortStep.objects.select_related("users")
  File "/.venvs/core/lib/python3.11/site-packages/ormar/queryset/queryset.py", line 982, in get
    processed_rows = self._process_query_result_rows(rows)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/.venvs/core/lib/python3.11/site-packages/ormar/queryset/queryset.py", line 196, in _process_query_result_rows
    return self.model.merge_instances_list(result_rows)  # type: ignore
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/.venvs/core/lib/python3.11/site-packages/ormar/models/mixins/merge_mixin.py", line 43, in merge_instances_list
    model = cls.merge_two_instances(next_model, model)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/.venvs/core/lib/python3.11/site-packages/ormar/models/mixins/merge_mixin.py", line 91, in merge_two_instances
    cls.merge_two_instances(
  File "/.venvs/core/lib/python3.11/site-packages/ormar/models/mixins/merge_mixin.py", line 91, in merge_two_instances
    cls.merge_two_instances(
  File "/.venvs/core/lib/python3.11/site-packages/ormar/models/mixins/merge_mixin.py", line 82, in merge_two_instances
    setattr(other, field_name, value_to_set)
  File "/.venvs/core/lib/python3.11/site-packages/ormar/models/newbasemodel.py", line 175, in __setattr__
    object.__setattr__(self, name, value)
  File "/.venvs/core/lib/python3.11/site-packages/ormar/models/descriptors/descriptors.py", line 110, in __set__
    model = instance.Meta.model_fields[self.name].expand_relationship(
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/.venvs/core/lib/python3.11/site-packages/ormar/fields/foreign_key.py", line 541, in expand_relationship
    model = constructors.get(  # type: ignore
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/.venvs/core/lib/python3.11/site-packages/ormar/fields/foreign_key.py", line 399, in _extract_model_from_sequence
    return [
           ^
  File "/.venvs/core/lib/python3.11/site-packages/ormar/fields/foreign_key.py", line 400, in <listcomp>
    self.expand_relationship(  # type: ignore
  File "/.venvs/core/lib/python3.11/site-packages/ormar/fields/foreign_key.py", line 541, in expand_relationship
    model = constructors.get(  # type: ignore
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/.venvs/core/lib/python3.11/site-packages/ormar/fields/foreign_key.py", line 475, in _construct_model_from_pk
    raise RelationshipInstanceError(
ormar.exceptions.RelationshipInstanceError: Relationship error - ForeignKey EffortResource is of type <class 'int'> while <class 'weakref.ProxyType'> passed as a parameter.

Versions (please complete the following information):

  • Database backend used (mysql/sqlite/postgress): postgres 14.1
  • Python version: 3.11
  • ormar version: 0.12.0
  • if applicable fastapi version 0.88

Thanks!

Maybe this can help you, even though it's been a long time.

I found the model cannot use mix-in or inheritance, otherwise the meta data will be deranged.

But if you define all models without mixin or inheritance, it will be ok.