strawberry-django icon indicating copy to clipboard operation
strawberry-django copied to clipboard

Strawberry Django Plus migration problem: get_queryset for nested fields

Open iamcrookedman opened this issue 11 months ago • 3 comments

Request:

{
  standConnection{
    edges{
      node{
        planningAreas{
          id
        }
      }
    }
  }
}

Models:

class PlanningArea(models.Model):
    ...
    objects = PlanningAreaQuerySet.as_manager()

class Stand(models.Model):
    ...
    objects = StandManager()

Types:

class BaseAccessResolverNodeTypeMixin:
    @classmethod
    def get_queryset(cls, queryset: BaseModelAvailableQuerySet, info: Info, **kwargs) -> BaseModelAvailableQuerySet:
        return queryset.filter_available(user=info.context.request.user)
        

@strawberry.django.type(PlanningArea)
class PlanningAreaGqlType(BaseAccessResolverNodeTypeMixin, relay.Node):
    name: auto
    ...


@strawberry.django.type(Stand)
class StandGqlType(BaseAccessResolverNodeTypeMixin, relay.Node):
    planning_areas: list[Annotated["PlanningAreaGqlType", lazy("apps.planning_areas.gql.types")]]
    ...

For both models, the objects manager was redefined and it is inherited from BaseModelAvailableQuerySet

The problem is the following: when I make a request it starts calling get_queryset method for PlanningAreaGqlType (the old library did not have this behavior) and it fails with an error AttributeError: 'QuerySet' object has no attribute 'filter_available'

Everything is fine for the latest version of strawberry-django-plus lib

Upvote & Fund

  • We're using Polar.sh so you can upvote and help fund this issue.
  • We receive the funding once the issue is completed & confirmed by you.
  • Thank you in advance for helping prioritize & fund our backlog.
Fund with Polar

iamcrookedman avatar Jul 20 '23 09:07 iamcrookedman

Hey @iamcrookedman ,

What is happening here is that there was an issue at strawberr-graphql-django, which strawberry-django-plus used to use as well, and got fixed together with the merge.

When you have a nested related manager, django will use the _base_manager instead of the instead of the _default_manager, which is set to the one you define on objects. You can read at the django documentation why it does that.

Previously strawberry-graphql-django used to use .objects.all() instead of ._base_manager.all(), which goes against og what should be used based on the django documentation, and it is not what users would expect.

Having said that, if you want your model to always use your custom manager, you can override its _base_manager, but ideally you will probably want to consider if you really want nested manager to use your custom manager, due to the reasons mentioned on the django documentation.

bellini666 avatar Jul 20 '23 18:07 bellini666

Marking this as documentation since it would be nice to add some documentation about how this works

bellini666 avatar Jul 30 '23 16:07 bellini666