Custom relation field for django-rest-framework's serializers
Project description
DRF Custom Related Field
This is a Django REST Framework's PrimaryKeyRelatedField like field which
allows you to pass custom fields (instead of default pk) to serialize relation.
Requirements
- Python 3.6+
- Django 2+
- djangorestframework 3+
Installation
pip install drf-custom-related-field
Usage
For example, we have following model structure:
from django.db import models
class Company(models.Model):
name = models.CharField(max_length=100)
country = models.CharField(max_length=100)
def upper_name(self):
return self.name.upper()
class Address(models.Model):
street = models.CharField(max_length=255)
building = models.CharField(max_length=255)
def full_address(self):
return f'{self.street}, {self.building}'
class WorkingBuilding(models.Model):
capacity = models.IntegerField(default=0)
address = models.ForeignKey(Address, on_delete=models.CASCADE)
class Employee(models.Model):
username = models.CharField(max_length=100)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
workplace = models.ForeignKey(WorkingBuilding, null=True, on_delete=models.CASCADE, related_name='employees')
And we have following instances:
work_address = Address.objects.create(street='Main st.', building='10')
workplace = WorkingBuilding.objects.create(capacity=200, address=work_address)
company = Company.objects.create(name='Great Inc.', country='US', )
employee = Employee.objects.create(username='ckkz', company=company, workplace=workplace)
Examples:
-
Map custom field for read only
class EmployeeSerializer(serializers.ModelSerializer): company = CustomRelatedField(queryset=Company.objects, field_name='name') class Meta: model = Employee fields = ('username', 'company') serializer = EmployeeSerializer(employee) assert serializer.data['company'] == company.name
{ "username": "ckkz", "company": "Great Inc." }
-
Assign new value by custom field (
namein this case)class EmployeeSerializer(serializers.ModelSerializer): company = CustomRelatedField(queryset=Company.objects, field_name='name') class Meta: model = Employee fields = ('username', 'company') new_company = Company.objects.create(name='New Company', country='RU') serializer = EmployeeSerializer(employee, data={'company': new_company.name}, partial=True) serializer.is_valid(raise_exception=True) serializer.save() employee.refresh_from_db() assert employee.company_id == new_company.id
{ "username": "ckkz", "company": "New Company" }
-
Use
many=Trueclass WorkingBuildingSerializer(serializers.ModelSerializer): employees = CustomRelatedField(field_name='username', many=True, read_only=True) class Meta: model = WorkingBuilding fields = ('capacity', 'employees') serializer = WorkingBuildingSerializer(workplace) assert len(serializer.data['employees']) == workplace.employees.count()
{ "capacity": 200, "employees": ["ckkz"] }
-
Use nested (dotted) relations and callable model fields
class EmployeeSerializer(serializers.ModelSerializer): workplace = CustomRelatedField(source='workplace.address', field_name='full_address', read_only=True) class Meta: model = Employee fields = ('username', 'workplace') serializer = EmployeeSerializer(employee) assert serializer.data['workplace'] == employee.workplace.address.full_address()
{ "username": "ckkz", "workplace": "Main st., 10" }
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters