Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to exclude fields by default? #303

Open
Alejandroid17 opened this issue Mar 18, 2022 · 2 comments
Open

Is it possible to exclude fields by default? #303

Alejandroid17 opened this issue Mar 18, 2022 · 2 comments

Comments

@Alejandroid17
Copy link

Is it possible to exclude fields by default? I have a serializer with a serialized field with a lot of data. This data will be used in some specific cases, but not always.

class BookSerializer(DynamicFieldsMixin, serializer.ModelSerializer):
    ....

    class Meta:
        model = Book
        fields = ['id', 'name',  '...']

class UserSerializer(DynamicFieldsMixin, serializer.ModelSerializer):
    books = BookSerializer(many=True, read_only=True)
    ....

    class Meta:
        model = User
        fields = ['id', 'username', 'email', '...', 'books']

Imagine a user with 500 books. In my logic I normally don't need to know information about those 500 books, but I do need to know information about the user (this is not a real example).

I could exclude using the query GET /user/1?query={username, -books} but it forces me to put it everywhere where it is consumed.

The idea would be something like:

class UserSerializer(DynamicFieldsMixin, serializer.ModelSerializer):
    books = BookSerializer(many=True, read_only=True)
    ....

    class Meta:
        model = User
        fields = ['id', 'username', 'email', '...', 'books']
        default_exclude = ['books']

Default:

 # `GET /user/1`

{
    "id": 100
    "username": "dummy",
    "....": "....", # without the "books" field
},

With books field:

 # `GET /user/1?query={id, username, books}`

{
    "id": 100
    "username": "dummy",
    "books": [ ..... ]
}

Thank you for everything!

@sommelon
Copy link

The example you wrote looks possible by overriding the DynamicFieldsMixin.get_parsed_restql_query like this:

    def get_parsed_restql_query(self):
        request = self.context.get('request')

        if request is not None and self.has_restql_query_param(request):  # Check query parameter first
            # Get from request query parameter
            return self.get_parsed_restql_query_from_req(request)
        elif self.dynamic_fields_mixin_kwargs["query"] is not None:  # Check serializer argument second
            # Get from query kwarg
            return self.get_parsed_restql_query_from_query_kwarg()
        elif self.dynamic_fields_mixin_kwargs["parsed_query"] is not None:
            # Get from parsed_query kwarg
            return self.dynamic_fields_mixin_kwargs["parsed_query"]
        return None  # There is no query so we return None as a parsed query

and overriding GenericAPIView.get_serializer like this:

    def get_serializer(self, *args, **kwargs):
        serializer_class = self.get_serializer_class()
        kwargs.setdefault('context', self.get_serializer_context())
        return serializer_class(*args, query="{-books}", **kwargs)

(or just passing the query="{-books}" to a serializer, if you aren't using the get_serializer method).
BUT this just prioritizes the query parameter from the request over the query argument to serializer. So if you did provide the query parameter (e.g. ?query={-username}), you would still get books, they won't be excluded.

{
    id,
    books,
    ... # everything except username
}

@dnievas04
Copy link

Would it be possible to extend the concept more generically? We could add an extra parameter, named for example "lazy_load" in the serializer we are using, where fields marked as such would only be loaded when explicitly specified in the query parameters, allowing for on-demand data retrieval. 

I love this project, and we are currently using it in our production software. However, I believe that this feature would help sometimes minimize data overfetching for our endpoints while reusing existing serializers.

The example at the beginning of the thread perfectly illustrates the requirement. Keeping in mind that we are working with a REST architectural style, if we want to GET information about users, the ideal approach would be to bring only the information associated with the user initially. If we eventually need more information, we can explicitly ask for it with this excellent tool

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants