Improved interaction with DRF relations.
Project description
AIR-DRF-RELATION
Table of Contents
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
- extra_kwargs
in Meta
- hidden_fields
- action_hidden_fields
- action_read_only_fields
- action_extra_kwargs
- 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')
Nested save objects
You can use the NestedFactory
functionality to easily create or update objects by nested fields. NestedFactory stores primary keys by default. But you can delete objects and create new ones every time.
Only use NestedFactory in simple cases!
Saving nested objects without NestedFactory
class CabinetSerializer(ModelSerializer):
class Meta:
model = Cabinet
fields = ('id', 'name', 'code') # you should hide or set read_only on 'school' field
class SchoolDefaultNestedSerializer(ModelSerializer):
cabinets = CabinetSerializer(many=True)
class Meta:
model = School
fields = ('id', 'name', 'cabinets')
def create(self, validated_data):
cabinets = validated_data.pop('cabinets', [])
instance = School.objects.create(**validated_data)
for el in cabinets:
Cabinet.objects.create(**el, school=instance)
return instance
def update(self, instance: School, validated_data):
cabinets = validated_data.pop('cabinets', [])
instance.cabinets.all().delete()
instance.__dict__.update(validated_data)
instance.save()
for el in cabinets:
Cabinet.objects.create(**el, school=instance)
return instance
Saving nested objects with NestedFactory
class CabinetSerializer(ModelSerializer):
class Meta:
model = Cabinet
fields = ('id', 'name', 'code', 'school') # 'school' field is required
class SchoolCustomNestedSerializer(ModelSerializer):
cabinets = CabinetSerializer(many=True)
class Meta:
model = School
fields = ('id', 'name', 'cabinets')
def save_nested(self, validated_data, instance=None):
factory = NestedSaveFactory(serializer=self, nested_save_fields=['cabinets'])
factory.set_data(validated_data=validated_data, instance=instance)
return factory.save_instance().save_nested_fields().instance
def create(self, validated_data):
return self.save_nested(validated_data=validated_data)
def update(self, instance, validated_data):
return self.save_nested(validated_data=validated_data, instance=instance)
Using NestedFactory in AirModelSerializer
class CabinetSerializer(ModelSerializer):
class Meta:
model = Cabinet
fields = ('id', 'name', 'code', 'school') # 'school' field is required
class SchoolAutoNestedSerializer(ModelSerializer):
cabinets = CabinetSerializer(many=True)
class Meta:
model = School
fields = ('id', 'name', 'cabinets')
nested_save_fields = ('cabinets',)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file air_drf_relation-0.2.3.tar.gz
.
File metadata
- Download URL: air_drf_relation-0.2.3.tar.gz
- Upload date:
- Size: 27.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.4.1 importlib_metadata/4.6.0 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.61.1 CPython/3.9.5
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5c89bd407af8f4b42e0abef39cf53f00ae7abed33b83d506d9e7a9bb182def52 |
|
MD5 | 41a1245a960918358da32f4535f5fe5f |
|
BLAKE2b-256 | 94a51c7df3b50e383d07081c699f97f973474988ca173433a86f61355b771da5 |