I have a HyperlinkedModelSerializer
. To implement its validate
method properly, I need to access the primary key or the URL of the object that is being validated – if it has one, i.e. if it's being edited, not created. What's the correct way of doing that?
I tried many things, but the only approach that worked was a hack that fetches the ID of the object when the serializer is instantiated into it's id
field:
class BoxSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Box
fields = ('id', 'name', 'url')
def __init__(self, *args, **kwargs):
super(BoxSerializer, self).__init__(*args, **kwargs)
self.id = None \
if len(args) != 1 or not isinstance(args[0], Box) \
else args[0].id
def validate(self, data):
print(data)
return data
What's the proper way to access the ID/URL of the object being validated from within the serializer's validate
method? Neither data['id']
nor data['url']
exist.
urls.py
:
urlpatterns = [
url(r'(?P<pk>[0-9]+)/$', views.BoxDetail.as_view(), name='box-detail'),
]
views.py
:
class BoxDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Box.objects.all()
serializer_class = BoxSerializer
You can access the id
of the object being edited by self.instance
.
From the DRF serializers docs on Accessing the initial data and instance:
When passing an initial object or queryset to a serializer instance, the object will be made available as
.instance
. If no initial object is passed then the.instance
attribute will beNone
.
Since you are using HyperLinkedModelSerializer
, you will have access to the object being edited in case of PUT
requests as an instance
attribute set on the serializer. You can use this instance
attribute to access the id
of the object being edited by doing self.instance.id
.
You can write your validation logic in validate()
function then after getting the object id in the variable object_id
. This will not affect create requests as instance
will not be set on the serializer then.
class BoxSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Box
fields = ('id', 'name', 'url')
def validate(self, data):
if self.instance: # 'instance' will be set in case of `PUT` request i.e update
object_id = self.instance.id # get the 'id' for the instance
# write your validation logic based on the object id here
return data
Another way to access the object id is by accessing the kwargs
from the view
object in the serializer context
dictionary.
my_view = self.context['view'] # get the 'view' object from serializer context
object_id = my_view.kwargs.get('pk') # access the 'view' kwargs and lookup for 'pk'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With