Skip to content

FAQ

Does this replace GraphQL?

Not really — it gives REST APIs the field-selection ergonomics people usually reach for GraphQL to get, without adopting a schema/resolver layer, a new query language on the wire, or GraphQL-specific tooling. If you need client-defined queries across arbitrary relations with a single round trip and your team is prepared to operate a GraphQL layer, that's still a reasonable choice. If you have an existing REST API and want to cut over-fetching without a rewrite, this is the lower-cost path.

Does it work with ModelViewSet's create/update?

Yes, output filtering and query optimization both work across every action. By default, fields= is ignored on unsafe methods (POST/PUT/PATCH/DELETE) — see SAFE_METHODS_ONLY — so a POST response always reflects the full default representation unless you deliberately disable that guard.

Can clients request fields that don't exist?

By default, yes, silently — the response just won't contain a field by that name. Set STRICT = True to turn this into an explicit 400 Bad Request.

Does this expose fields that would otherwise be hidden?

No. ?fields= can only narrow the set of fields a serializer would have exposed anyway. It has no ability to add fields that aren't declared on the serializer, and any permission-based field hiding you implement in get_fields() (see Common Patterns) still applies — this package's filtering runs on top of, not instead of, your own field logic.

Why do I need the mixin on nested serializers too?

Each serializer instance is responsible for filtering its own level of the response tree — there's no global registry rewriting fields across every serializer in a project. If a nested serializer doesn't use PartialFieldsSerializerMixin, it renders its full default representation regardless of what the client requested for it. This is a deliberate design choice: it keeps the mixin's behavior local and predictable rather than depending on implicit, action-at-a-distance configuration.

Does the optimizer ever get it wrong and break my API?

No — see Architecture: the optimizer is deliberately conservative and only ever adds select_related / prefetch_related / only(), never changes what data is returned. If it can't confidently map a field to a model relation or column, it leaves that field alone (falls back to normal, unoptimized attribute access) — see Troubleshooting for the specific cases.

Can I use this with django-filter, django-guardian, multi-tenancy packages, etc.?

Yes — this package only touches get_queryset() (adding select_related/prefetch_related/only()) and get_fields() on the serializer. It composes with any other get_queryset() override or serializer field logic already in your MRO. See Advanced Usage.

Does this support GraphQL-style field aliasing collisions?

If a client aliases two different fields to the same output key (?fields=a:x,a:y), that's rejected at parse time as a duplicate field name within the same group (a would be requested twice) — see Troubleshooting.

Is this thread-safe / safe for async views?

Yes. There is no shared mutable state between requests — FieldTree is an immutable, frozen dataclass, and PartialResponseMixin caches the parsed tree per view instance, and DRF creates a new view instance per request (both sync and async).

Why isn't there a management command or Django admin integration?

The scope of this package is deliberately narrow: serializer field filtering and queryset optimization for the DRF request/response cycle. Django admin uses its own ModelAdmin/form machinery, which this package doesn't touch.