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

      

+3


source to share


2 answers


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 be None

.

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' 

      

+3


source


Call the serializer with the attribute context

.

serializer = BoxSerializer(queryset, context={'request': self.request}, ...)

      



Now you can access the object request

from within the function validate

with

self.context['request']['id']

      

0


source







All Articles