Search code examples
djangorestdjango-rest-frameworkapi-designhateoas

Does the model, the view or the serializer represent a REST resource in Django Rest Framework?


I am building an API using Django Rest Framework, and I'm trying to make it as RESTful as possible. Following this question (and also this question on SoftwareEngineering), I have described a number of resources that my API endpoints will expose, such as an Invoice that can be seen at the following URL: /api/v1/invoices/<invoicenumber>/

However, I am having trouble relating the RESTful design principles to the concrete workings of Django Rest Framework. It is unclear to me what constitues a resource: the model, the serializer or the view?

In particular, I am confused about the correct place to implement my calculate_total() method. In a regular Django application it would certainly live in the the Invoice model:

class InvoiceModel(models.Model):
    def calculate_total(self):
         # do calculation
         return total

Although the actual calculation could be complex, the "total" is conceptually a part of the representation of the Invoice. In this sense, the resource is more equivalent to the InvoiceSerializer:

class InvoiceSerializer(serializers.Serializer):
    total = serializers.SerializerMethodField()

    def get_total(self, obj):
        # do calculation
        return total

Finally, the resource will always be accessed by a view. So you could also argue that the view is actually the resource, while the serializer and the model are simply implementation details:

class InvoiceView(APIView):
    def calculate_total(self, obj):
        # do calculation
        return total

If I would have to designate one of the above classes as the canonical representation of the Invoice as a resource, which one would it be? Should I implement my method on the model class, the serializer class, or the view class? Or perhaps I am overthinking this and any one of them will do?


Solution

  • Well, although I agree that there might be different solutions, In this case I would definitely go with the model. As the resource and the place where to put the function.

    In the case of the function, it could even be implemented as a calculated attribute of the invoice. Actually, to me TOTAL looks more like an attribute that a method.

    Anyway, it seems interesting to me your train of thought and how you get to the other two options, serializer and the view.

    I think that the model it is definitely a resource. In this case for me, the invoice resource is the model. So I would say that every model that your API is going to publish, is a resource.

    I also think that whenever the resource is not directly related to a single model, the view could be considered the resource.

    Now, the serializer is an enigma to me. I can't think of a case that it could be think it as a resource.