Django REST Framework: get id / url during validation?
I have HyperlinkedModelSerializer
. To properly implement my method validate
, I need to access the primary key or url of the object being checked - if there is one, i.e. If it is being edited, not created. What is the correct way to do this?
I've tried a lot of things, but the only approach that worked was a hack that retrieves the object id when the serializer is created on the field id
:
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 is the correct way to access the ID / url of the object being checked from the serializer method validate
? No data['id']
, no data['url']
do not 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
source to share
You can access the id
editable object self.instance
.
From the DRF Serial Converter docs on Source Data and Instance Access:
When you pass a source object or set of requests to a serializer instance, the object will be available as
.instance
. If the initial object then the attribute.instance
will beNone
.
Since you are using HyperLinkedModelSerializer
, you will have access to the editable object in case of PUT
requests as an attribute instance
set in the serializer. You can use this attribute instance
to access the id
editable object by running self.instance.id
.
You can write your validation logic in validate()
, then after getting the object id in a variable object_id
. This will not affect create requests as instance
it will not be set in the serializer.
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 an object identifier is to access kwargs
from an object view
in the serialator dictionary context
.
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'
source to share