air-drf-relation

Improved interaction with DRF relations.


Keywords
django, rest, relation, nested, pk, primary, object
License
MIT
Install
pip install air-drf-relation==0.6.0

Documentation

AIR-DRF-RELATION

Table of Contents

  1. Instalation
  2. About
  3. AirRelatedField
    1. pk_only
    2. hidden
  4. AirModelSerializer
    1. user
    2. extra_kwargs
    3. hidden_fields
    4. Kwargs by actions
      1. action_read_only_fields
      2. action_hidden_fields
      3. action_extra_kwargs
    5. Priority extra_kwargs
    6. Filter nested querysets

Instalation

$ pip install air-drf-relation

About

air-drf-relation adds flexibility and convenience in working with ModelSerializer.

AirRelatedField

Used to extend the functionality of the PrimaryKeyRelatedField

class BookSerializer(ModelSerializer):
    # author = PrimaryKeyRelatedField(queryset=Author.objects) - default usage
    author = AirRelatedField(AuthorSerializer)
    city = AirRelatedField(CitySerializer)

    class Meta:
        model = Book
        fields = ('uuid', 'name', 'author', 'city')

AirRelatedField allows you to get not only pk but also an object with pk, which will be searched.

{
    "name": "demo",
    "author": { 
        "id": 1
    },
    "city": 1
}

pk_only

Automatically AirRelatedField returns a serialized object. If you only want to use pk, you must specify the pk_only key.

author = AirRelatedField(AuthorSerializer, pk_only=True)

hidden

Hidden fields are not used for serialization and validation. The data will be returned without fields. Usually used together in AirModelSerializer

author = AirRelatedField(AuthorSerializer, hidden=True)

Important

You cannot use hidden and pk_only in ModelSerializer and with extra_kwargs

AirModelSerializer

Used to extend the functionality of the ModelSerializer

class BookSerializer(AirModelSerializer): # full example
    author = AirRelatedField(AuthorSerializer)
    city = AirRelatedField(AuthorSerializer)

    class Meta:
        model = Book
        fields = ('uuid', 'name', 'author', 'city')
        hidden_fields = ()
        read_only_fields = () # default read_only_fields
        extra_kwargs = {} # default extra_kwargs with support custom keys
        action_read_only_fields = {
            'create': {},
            '_': {} # used for other actions
        },
        action_hidden_fields = {
            'create': (),
            '_': ()
        }
        action_extra_kwargs = {
            'list': {},
            '_': {}
        }
        nested_save_fields = ()

user

User is automatically put from the request if available. You can also set the user manually.

class DemoSerializer(AirModelSerializer):
    class Meta:
        fields = ('id', 'name')
    
    validate_name(self, value):
        if not self.user:
            return None
        return value

Manually set user.

serializer = DemoSerializer(data={'name': 'demo'}, user=request.user)

extra_kwargs

Extends the standard work with extra_kwargs by adding work with additional attributes. You can also transfer extra_kwargs manually.

class BookSerializer(AirModelSerializer):
    author = AirRelatedField(AuthorSerializer)
    
    class Meta:
        fields = ('id', 'name', 'author')
        extra_kwargs = {
            'author': {'pk_only': True},
            'name': {'hidden': True}
        }

hidden_fields

Hides fields for validation and seralization.

class BookSerializer(AirModelSerializer):
    class Meta:
        fields = ('id', 'name', 'author')
        hidden_fields = ('name', 'author')

Kwargs by actions

Kwargs by actions is used only when the event. You can pass acions separated by ,. For events that don't match, you can use _ key. It is used if action is passed. Action is set automatically from the ViewSet, or it can be passed manually.

class DemoViewSet(ModelViewSet):
    queryset = Demo.objects.all()
    serializer_class = DemoSerializer
    
    def perform_create(serializer, request):
        action = serializer.action # action is 'create'
        serializer.save()
    
    @action(methods=['POST'], detail=False)
    def demo_action(self, request):
        serializer = self.get_serializer_class()
        action = serializer.action # action is 'demo_action'

Manually set action.

serializer = DemoSerializer(data={'name': 'demo'}, action='custom_action')
action = serializer.action # action is 'custom_action'

action_read_only_fields

Sets read_only_fields by action in serializer.

class BookSerializer(AirModelSerializer):
    class Meta:
        fields = ('id', 'name', 'author')
        action_read_only_fields = {
            'create,update': ('name', 'author')
        }

action_hidden_fields

Sets hidden_fields by action in serializer.

class BookSerializer(AirModelSerializer):
    class Meta:
        fields = ('id', 'name', 'author')
        action_hidden_fields = {
            'custom_action': ('author', ),
            '_': ('id', )
        }

action_extra_kwargs

Expand extra_kwargs by action in serializer.

class BookSerializer(AirModelSerializer):
    author = AirRelatedField(AuthorSerializer, pk_only=True, null=True)
    
    class Meta:
        fields = ('id', 'name', 'author')
        action_extra_kwargs = {
            'create,custom_update': {
                'author': {'pk_only': False, 'null'=True}
            }
        }

Priority extra_kwargs

Below are the priorities of the extra_kwargs extension in ascending order

  1. extra_kwargs in Meta
  2. hidden_fields
  3. action_hidden_fields
  4. action_read_only_fields
  5. action_extra_kwargs
  6. extra_kwargs manually transmitted

Filter nested querysets

AirModelSerializer allows you to filter the queryset by nested fields.

class BookSerializer(AirModelSerializer):
    city = AirRelatedField(CitySerializer, queryset_function_name='custom_filter')

    def queryset_author(self, queryset):
        return queryset.filter(active=True, created_by=self.user)

    def filter_city_by_active(self, queryset):
        return queryset.filter(active=True)

    class Meta:
        model = Book
        fields = ('uuid', 'name', 'author', 'city')