[Fixed]-Django rest framework where to write complex logic in serializer.py or views.py?

22👍

Personally I prefer to have the business logic separated from both view and serializer. I usually create a new class with the business logic which can be used in both serializer and view based on necessity. Basically I treat it as a service. Reason for that is:

  1. Makes the code cleaner(no thick and thin stuff).
  2. Writing tests for those business logic is easier.
  3. You can use that this business logic service in both view and serializer, depending on your need.
  4. while testing APIs, you can mock those buiness logic if needed.
  5. Reuse any logic in multiple places.

An example would be like this:

class BusinessLogicService(object):

    def __init__(self, request):
       self.request = request

    def do_some_logical_ops(self, data_required_one, data_required_two):
        # do processing
        return processed_data

Example usage in serializer:

class SomeSerializer(serializer.Serialize):
     ...
     def create(self, validated_data):
         business_logic_data = BusinessLogicService(self.request).do_some_logical_ops(**validated_data)
         return Model.objects.create(**business_logic_data)
👤ruddra

7👍

I’ve asked a similar question about this before. Actually, it depends on what logic you are going to adapt. After doing further research, I have come up with some approaches. Here are my suggestions:

  1. If you want to add some logic before doing serializer validation, it is better to include that in your view (eg. override your views create method). An example to this case would be; your POST body does not contain a value that is needed by the serializer hence is not valid yet, so add that in your view’s create function.
  2. If you are doing some custom authentication logic, such as parsing a custom token in your http header, do it in your view as well, because serializer has nothing to do with it. Moreover, you can create your own authentication decorator for that.
  3. If you want to add logic which is directly related to the representation of your data, such as an adaptation of a timestamp from UTC to some other, you can add in your serializer as it is directly related to your object representation. You can use SerializerMethodField etc. to do that.

3👍

I try to segregate it on the basis of requirements of the context. Like:

  • If I’m supposed to deal with the request object(like current user), I try to implement that in view.
  • If I need to deal with querying models to create a view I would switch to serializer.

It may also depend upon how I’m planning to maintain the code (If I have huge number of views in a single file, I will try to avoid implementing logical stuffs as much as possible).

Leave a comment