encode / django-rest-framework

Web APIs for Django. 🎸
https://www.django-rest-framework.org
Other
27.83k stars 6.76k forks source link

Automatic Inclusion of @property Fields in ModelSerializer #9413

Closed irshadirshu0722 closed 1 month ago

irshadirshu0722 commented 1 month ago

Overview

Backend developers often face the challenge of manually adding @property fields to serializers using SerializerMethodField. This process can be repetitive and error-prone. To simplify and expedite the inclusion of @property fields, we've introduced a new feature in the ModelSerializer that allows you to automatically include these fields with minimal configuration.

Feature Description

With this new feature, you can easily include @property fields in your ModelSerializer by setting the property_fields attribute in the serializer's Meta class. You have the option to include all @property fields or manually specify which ones to include.

Usage

  1. Include All @property Fields: Set property_fields to all in the Meta class to automatically include all @property fields.

     class MyModelSerializer(ModelSerializer):
          class Meta:
               model = MyModel
               fields = '__all__'
               property_fields = '__all__'
  2. Manually Specify @property Fields: Provide a list or tuple of @property field names to include only specific fields.

     class MyModelSerializer(ModelSerializer):
          class Meta:
               model = MyModel
               fields = '__all__'
               property_fields = ('property_field1', 'property_field2')

Implementation

The feature is implemented in the get_fields method of the ModelSerializer. Here’s the relevant code:

     def get_fields(self):
            ...
         property_fields = getattr(self.Meta, 'property_fields', ())
         if property_fields:
             if property_fields == '__all__':
                 for attr_name in dir(model):
                     attr = getattr(model, attr_name)
                     if isinstance(attr, property):
                        fields[attr_name] = serializers.ReadOnlyField()
             elif isinstance(property_fields, list) or isinstance(property_fields, tuple):
                 for attr_name in property_fields:
                     attr = getattr(model, attr_name, None)
                     if not attr:
                         raise ValueError(f"{attr_name} doesn't exist in {model} model properties")
                     if isinstance(attr, property):
                         fields[attr_name] = serializers.ReadOnlyField()
             else:
                 raise ValueError(
                     "Please select the appropriate value for property_fields in the serializer. "
                     "Use '__all__' to include all property fields, or provide a tuple or list to manually specify the property fields you want to include."
                 )
         ...

Benefits

This feature significantly enhances the efficiency of working with @property fields in Django REST Framework serializers. By setting a single attribute in the Meta class, developers can now easily include these fields, making their code cleaner and more maintainable.

Feel free to use this feature in your projects and contribute any improvements or suggestions. Happy coding!