Django Rest Framework generic views, so clunky to get the object/instance

36 Views Asked by At

Often I wish to use the created/updated object, for say to log it in some history, or use it in an email.

E.g.1. CreateAPIView

    def create(self, request, *args, **kwargs):
        ret = super().create(request, *args, **kwargs)
        # Do something with the create object here, e.g. create a history log
        return ret

E.g.2. UpdateAPIView

    def update(self, request, *args, **kwargs):
        ret = super().update(request, *args, **kwargs)
        # Do something with the create object here, e.g. create a history log
        return ret

Answers that are not solutions

  1. Use ret.data to see a dict of the object data ... because I wish to access the object so so I can look up foreign keys, call methods on it etc.
  2. Create a new object using ret.data ... wasteful to create object, through it away, and recreate it again
  3. Copy and paste most of the original create/update method just so one can save a reference to the object ... this is terrible because it's the meat of the generic view, so why event use it in the first place.
  4. The best I have come up:

A CreateAPIView, e.g.:

    def perform_create(self, serializer):
        self.object = serializer.save()
        return self.object

    def create(self, request, *args, **kwargs):
        ret = super().create(request, *args, **kwargs)
        # Do something with self.object
        return ret

An UpdateAPIView, e.g.:

    def get_object(self):
        self.object = super().get_object()
        return self.object

    def update(self, request, *args, **kwargs):
        ret = super().update(request, *args, **kwargs)
        # Do something with the self.object
        return ret

I feel like this is such a common use case, I come across so often, there must be a built in, more idiomatic "DRF" way to do it.

1

There are 1 best solutions below

1
MohammadBagherSoltani On

A good coding practice here is to have a get_object function in the view class such as:

def get_object(self, pk):
    try:
        return Model.objects.get(pk=pk)
    except Model.DoesNotExist:
        raise Http404

And then use it in other functions such as update:

def update(self, request, *args, **kwargs):
    ret = self.get_object(request.data.pk).update(request.data, *args, **kwargs)
    # Do something with the self.object
    return ret 

Check out the official DRF tutorial.