Extended utilities for django rest framework
Project description
Rest Framework Utils
This is a utility package which currentlly supports writable nested serializers in Django Rest Framework.
Installation
pip install drf-utilities
Usage
For example, consider the following models:
class User(models.Model):
phone = models.CharField(max_length=15, blank=True, null=True)
class UserDetail(models.Model):
user = models.OneToOneField(
User,
related_name="user_detail",
on_delete=models.RESTRICT
)
employeed_at = models.ForeignKey(
"users.Company",
related_name="employees",
null=True,
blank=True,
on_delete=models.CASCADE
)
projects = models.ManyToManyField(
"users.Project",
related_name="users",
blank=True
)
licenses = models.ManyToManyField(
"users.License",
related_name="users",
blank=True
)
class Company(models.Model):
name = models.CharField(max_length=255)
address = models.TextField()
owner = models.ForeignKey(
"users.UserDetail",
related_name="companies",
on_delete=models.CASCADE
)
class Certificate(models.Model):
user = models.ForeignKey(
"users.UserDetail",
related_name="certificates",
on_delete=models.CASCADE
)
name = models.CharField(max_length=255)
received_on = models.DateField()
expires_on = models.DateField(null=True, blank=True)
description = models.TextField(blank=True, null=True)
class Project(models.Model):
name = models.CharField(max_length=255)
description = models.TextField(blank=True)
start_date = models.DateField()
end_date = models.DateField(null=True, blank=True)
class License(models.Model):
primary_key = models.BigAutoField(primary_key=True)
name = models.CharField(max_length=255)
Create object with nested data
Let's say we want to create a UserDetail model object and also create Company, Project and License model in the same API request. Create following serializers first:
from rest_framework import serializers
from rest_framework_utils.serializers import WritableNestedSerializer
class CompanySerializer(WritableNestedSerializer):
awards = AwardSerializer(many=True)
class Meta:
model = Company
fields = [
"id",
"name",
"address",
"owner",
"awards"
]
class ProjectSerializer(serializers.ModelSerializer):
class Meta:
model = Project
fields = [
"id",
"name",
"description",
"start_date",
"end_date",
]
class LicenseSerializer(serializers.ModelSerializer):
class Meta:
model = License
fields = [
"primary_key",
"name"
]
Then create serializer for UserDetail model which extends WritableNestedSerializer
class UserDetailCreateSerializer(WritableNestedSerializer):
employeed_at = CompanySerializer()
projects = ProjectSerializer(many=True)
licenses = LicenseSerializer(many=True)
class Meta:
model = UserDetail
fields = [
"id",
"user",
"employeed_at",
"projects",
"licenses"
]
Pass input payload like below to create related objects of nested serializers:
{
"user": 1,
"employeed_at": {
"name": "Company Name",
"address": "Company address",
"owner": 7
},
"projects": [
{
"name": "Project Name",
"description": "Project Description",
"start_date": "2025-02-28",
"end_date": "2025-02-28"
}
],
"licenses": [
{
"name": "License Name"
}
]
}
This will create a Company, Project and License model objects with values provided in employeed_at, projects and licenses key.
If you want to link any existing company, project or license object with the newly created UserDetail object, you can use following input payload:
{
"user": 3,
"employeed_at": {
"id": 1,
"link": true
},
"projects": [
{
"name": "Project Name",
"description": "Project Description",
"start_date": "2025-02-28",
"end_date": "2025-02-28"
},
{
"id": 12,
"link": true
}
],
"licenses": [
{
"name": "User 3 test"
},
{
"primary_key": 18,
"link": true
}
]
}
Above request when completed creates UserDetail object with following data:
- Assign Company with id 1 to the created object.
- Create a new Project object with name "Project Name" and other provided data.
- As second json in projects key's list contains "id" and "link" key, this request will also assign the Project object with id 12 to created UserDetail object.
- Create one new License model object and assign License object with primary_key value 18 to UserDetail object.
NOTE: "id" and "primary_key" are the primary key columns of database. If your primary key column name for respective model is different, use that as key.
Update object with nested data
To Update UserDetail object and update Company, Project or License objects in the same request, use the following serializer:
class UserDetailUpdateSerializer(WritableNestedSerializer):
employeed_at = CompanySerializer()
projects = ProjectSerializer(many=True)
licenses = LicenseSerializer(many=True)
class Meta:
model = UserDetail
fields = [
"id",
"employeed_at",
"projects",
"licenses"
]
Pass the following as input payload to the API request:
{
"user": 3,
"employeed_at": {
"name": "Company Name",
"address": "Company Address",
"owner": 7
},
"projects": [
{
"name": "Project Name",
"description": "Project Description",
"start_date": "2025-02-28",
"end_date": "2025-02-28"
},
{
"id": 12,
"link": true
},
{
"id":13 ,
"name": "Updated Project Name",
"end_date": "2025-03-28"
}
],
"licenses": [
{
"name": "License Name"
},
{
"primary_key": 18,
"name": "Updated Name"
},
{
"primary_key": 17,
"link": false
}
]
}
Following changes will be made in UserDetail object when this request completes:
-
Create a new Company model object and assign it to the UserDetail object. If you want to set already created company, pass its primary key value pair along with "link" key and value true/false. If true, it will set employeed_at value to the object with primary key and if false, it will employeed_at to null.
-
Create a new project and assign it to object, assign project with provided id 12 to the object, update the project object with id 13 with provided values and assign it to UserDetail object. UserDetail object will have 3 project linked to the manyToMany field.
-
Create a new License object, update the License object name with primary_key 18, remove License object with primary_key 17(link=false) from ManyToMany field.
Note: Here the primary key column for Company and Project model is "id" and that of License is "primary_key". Hence, for "licenses" key, primary_key is used insted of "id". If your model's primary key column name is different, use that.
Set "link" key to true/false along with primary key value to add /remove OneToOne, ForeignKey or ManyToMany field values from UserDetail object.
Ignore Nested Serializer
If you want the class to ignore creation/updation of nested serializer data, pass the serializer field in ignore_serializer Meta option. It takes list of field names that needs to be ignored. You can write custom implementation for these fields by overriding create/update method of serializer.
class UserDetailUpdateSerializer(WritableNestedSerializer):
employeed_at = CompanySerializer()
projects = ProjectSerializer(many=True)
licenses = LicenseSerializer(many=True)
class Meta:
model = UserDetail
fields = [
"id",
"employeed_at",
"projects",
"licenses"
]
ignore_serializer=["projects"]
This serializer class will ignore data provided in projects key and not do any changes in it.
Nested Serializers with further Nested Serializer fields
If you have serializer fields which furthur have serializer fields in them:
- If serializer field has many=True(For ManyToMany fields), this class does not support such serializer fields.
- For ForeignKey and OneToOne fields, creation and updation needs to be managed in the serializer class of that serializer field itself. You can extend the class of serializer field by WritableNestedSerializer and it will work.
Consider following exaxmple:
class Awards(models.Model):
name = models.CharField(max_length=255)
received_on = models.DateField()
def __str__(self):
return self.name
class Company(models.Model):
name = models.CharField(max_length=255)
address = models.TextField()
owner = models.ForeignKey(
"users.UserDetail",
related_name="companies",
on_delete=models.CASCADE
)
awards = models.ManyToManyField(
"users.Awards", related_name="companies", blank=True
)
Lets say the Company model has a ManyToMany field with Awards model. You can create following serializers to create/update Copany model object along with creating/updating Award models ManyToMany field.
class CompanySerializer(WritableNestedSerializer):
awards = AwardSerializer(many=True)
class Meta:
model = Company
fields = [
"id",
"name",
"address",
"owner",
"awards"
]
class UserDetailUpdateSerializer(WritableNestedSerializer):
employeed_at = CompanySerializer()
projects = ProjectSerializer(many=True)
licenses = LicenseSerializer(many=True)
class Meta:
model = UserDetail
fields = [
"id",
"employeed_at",
"projects",
"licenses"
]
Pass following input payload to update UserDetail object along with Company and its Awards:
{
"employeed_at": {
"name": "Company Name",
"address": "Company Address",
"owner": 1,
"awards": [
{
"name": "Award Name",
"received_on": "2025-03-22"
},
{
"id": 1,
"link": true/false
},
{
"id": 2,
"name": "Updated name",
"received_on": "2025-03-22"
}
]
},
"projects": [
{
"name": "Project Name",
"description": "Project Description",
"start_date": "2025-03-22",
"end_date": "2025-03-22"
}
],
"licenses": [
{
"name": "License Name"
}
]
}
This will create a new Company object, assign Company object with id 1(link=true) and update the Company object with id 2 and assign it to the created Company object and assign this created Company object to UserDetail object.
Just in case if employeed_at was not a ForeignKey and a ManyToMany field in UserDetail model, and serializer would look like following:
class UserDetailCreateSerializer(WritableNestedSerializer):
employeed_at = CompanySerializer(many=True) #This is not supported
projects = ProjectSerializer(many=True)
licenses = LicenseSerializer(many=True)
class Meta:
model = UserDetail
fields = [
"id",
"user",
"employeed_at",
"projects",
"licenses"
]
This is not supported as CompanySerializer is having many=True and has furthur nested serializer field AwardSerializer.
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
File details
Details for the file drf_utilities-0.0.1.tar.gz.
File metadata
- Download URL: drf_utilities-0.0.1.tar.gz
- Upload date:
- Size: 9.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.10.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c76162b5b34b593daf0a45ea6d9c8442228f1bb748c0821f645932bca8938082
|
|
| MD5 |
da90e4301ab129ec9485d353ad51f6a1
|
|
| BLAKE2b-256 |
e18d71862e9cd0d9318965881a515861b1479fbc3e7b7e500e2071c1d1f9fb85
|
File details
Details for the file drf_utilities-0.0.1-py3-none-any.whl.
File metadata
- Download URL: drf_utilities-0.0.1-py3-none-any.whl
- Upload date:
- Size: 9.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.10.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
78a0d678c22bbcff0b81526ec2f7295719cfaf940d7c261146fe1861a5ec1696
|
|
| MD5 |
e9c2ea3bcf7776156718d0718e6fa857
|
|
| BLAKE2b-256 |
ba58b7f0b45983d5eae4edbc757dbb1c1ee148cd3e5df8c19fb41676a848e60d
|