0

I have Model, like:

 def SomeModel(models.Model):
     serial_num = models.IntegerField(unique=True)
     count = models.IntegerField()

And have to create 2 url which will work with this model. But, there are have to be 2 different serializers. For example:

  • For first url user’data have to has both fileds (serial_num and count) For second url users’data have to has only one field (count).
  • In second case serial_num will be generated in Serializers class.

Is this good practice to make 2 different serializers for one model?

And also question, what about validation?

Field “count” is depends on another model. I thought put validate into serializer class. But I don’t want to have 2 the same blocks of validation code in 2 different serializers classes (for both urls).

Mike
  • 860
  • 14
  • 24
  • I don't see a problem with using multiple serializers for 1 model - you only need separate views for each serializers for different behavior. – Chiefir Dec 27 '18 at 13:00
  • But what about validate? Both os serializers have to validate field "count" which depends on another model. – Mike Dec 27 '18 at 13:11
  • yep, you write different validations for each serializer. Of course, you can make it as a separate function and just call it inside serializers, to by DRY. – Chiefir Dec 27 '18 at 13:15
  • Then you can write a separate class (aka a Mixin) that encapsulates this validation and then apply this mixin (inherit from this class) to both serializers – ivissani Dec 27 '18 at 13:17
  • What is better way to validate models object? In Model's class or in Serializer class? – Mike Dec 27 '18 at 13:54
  • It depends. For your APIs I suggest to use on serializer. But notice if an item is created with django admin, then it will be passed any validation if validation is not on your models. So it depends On what you really need. – Reza Torkaman Ahmadi Dec 27 '18 at 16:02

3 Answers3

1

Create two serializers and assign each of your views to that specific serializer.

for example, imagine you have two path like path1 and path2:

class MyModelViewSet(ModelViewSet):
    serializer_class = Serializer1
    queryset = YourModel.objects.all()

    @action(methods=['post'], detail=False, url_path='path1', serializer_class=Serializer1)
    def path1_view(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        .....

    @action(methods=['post'], detail=False, url_path='path2', serializer_class=Serializer2)
    def path2_view(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        .....

and for serializers:

class Serializer1(ModelSerializer):
    class Meta:
        model = SomeModel
        fields = ('serial_num', 'count',)

class Serializer2(ModelSerializer):
    class Meta:
        model = SomeModel
        fields = ('count',)

    def validate(self, attrs):
        # Update attrs with serial_num here
        return attrs
Lucas Weyne
  • 1,107
  • 7
  • 17
Reza Torkaman Ahmadi
  • 2,958
  • 2
  • 20
  • 43
  • For viewset actions like `list`, `create`, `update`, etc you must override `get_serializer_class()` method and return the correct serializer class based on the `self.action` attribute. Check [this](https://stackoverflow.com/a/22755648/7727181) – Lucas Weyne Dec 27 '18 at 23:09
0

You should use two serializers and use inheritance for common validation logic.

0

I've found approach which may be more usefull. Use services for business logic. Example can read here: https://github.com/HackSoftware/django-styleguide#examples

Mike
  • 860
  • 14
  • 24