Skip to content

Confusing behavior of DynamicField.requires #373

Description

@d-ryzhykau

If the last part of the path in DynamicField.requires attribute is a relation and not a field name, the prefetch is not done. Example:

# models.py
from django.db import models


class Artist(models.Model):
    name = models.CharField(max_length=10)


class Album(models.Model):
    artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
    name = models.CharField(max_length=256)


class Song(models.Model):
    album = models.CharField(max_length=256)
    name = models.ForeignKey(Artist, on_delete=models.CASCADE)


# serializers.py
from dynamic_rest.serializers import DynamicModelSerializer
from dynamic_rest.fields import DynamicMethodField


class SongSerializer(DynamicModelSerializer):
    display_name = DynamicMethodField(requires=["album.artist"])

    class Meta:
        model = Song
        fields = ["pk", "display_name"]
    
    def get_display_name(self, song):
        return f"{song.album.artist.name} - {song.name} (from '{song.album.name}')"

If the display_name is requested, song.album will be prefetched, but song.album.artist won't be and will result in N+1 queries for each serialized Song object. This can be resolved by using album.artist.name, album.artist. or album.artist.* as the value of display_name.requires.
Is this the expected behavior? If so, it would be helpful to have it mentioned explicitly in the docs. Otherwise, it's necessary to fix the DynamicFilterBackend._build_implicit_prefetches method to include prefetches of relations with empty path remainders. Either way I'll be glad to provide a PR with fixes.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions