Skip to content

Commit 87a56b8

Browse files
committed
Implement nearly-stock DRF create() and update() functionality for synthetic CustomObjectSerializer
1 parent 643856f commit 87a56b8

File tree

1 file changed

+41
-0
lines changed

1 file changed

+41
-0
lines changed

netbox_custom_objects/api/serializers.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from rest_framework import serializers
99
from rest_framework.exceptions import ValidationError
1010
from rest_framework.reverse import reverse
11+
from rest_framework.utils import model_meta
1112

1213
from netbox_custom_objects import field_types
1314
from netbox_custom_objects.models import (CustomObject, CustomObjectType,
@@ -253,6 +254,44 @@ def get_display(self, obj):
253254
"""Get display representation of the object"""
254255
return str(obj)
255256

257+
# Stock DRF create() without raise_errors_on_nested_writes guard
258+
def create(self, validated_data):
259+
ModelClass = self.Meta.model
260+
261+
info = model_meta.get_field_info(ModelClass)
262+
many_to_many = {}
263+
for field_name, relation_info in info.relations.items():
264+
if relation_info.to_many and (field_name in validated_data):
265+
many_to_many[field_name] = validated_data.pop(field_name)
266+
267+
instance = ModelClass._default_manager.create(**validated_data)
268+
269+
if many_to_many:
270+
for field_name, value in many_to_many.items():
271+
field = getattr(instance, field_name)
272+
field.set(value)
273+
274+
return instance
275+
276+
# Stock DRF update() with custom field.set() for M2M
277+
def update(self, instance, validated_data):
278+
info = model_meta.get_field_info(instance)
279+
280+
m2m_fields = []
281+
for attr, value in validated_data.items():
282+
if attr in info.relations and info.relations[attr].to_many:
283+
m2m_fields.append((attr, value))
284+
else:
285+
setattr(instance, attr, value)
286+
287+
instance.save()
288+
289+
for attr, value in m2m_fields:
290+
field = getattr(instance, attr)
291+
field.set(value, clear=True)
292+
293+
return instance
294+
256295
# Create basic attributes for the serializer
257296
attrs = {
258297
"Meta": meta,
@@ -261,6 +300,8 @@ def get_display(self, obj):
261300
"get_url": get_url,
262301
"display": serializers.SerializerMethodField(),
263302
"get_display": get_display,
303+
"create": create,
304+
"update": update,
264305
}
265306

266307
for field in model_fields:

0 commit comments

Comments
 (0)