menu

Questions & Answers

How to get serializer data before response in DRF ListAPIView to order it by all fields?

I have two models.

class Team(models.Model):
    user = models.ManyToManyField(User, related_name='%(class)s_user')
    company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name='%(class)s_company')
    is_active = models.BooleanField(default=True)
    has_user = models.BooleanField(default=False)

    class Meta:
        app_label = 'accounts'


class TeamTranslation(models.Model):
    team_name = models.CharField(max_length=100)
    team_description = models.TextField()
    team = models.ForeignKey(Team, on_delete=models.CASCADE, related_name='%(class)s_team')
    languages = models.ForeignKey(Languages, on_delete=models.CASCADE, related_name='%(class)s_languages')
    is_active = models.BooleanField(default=True)

This is list view...

class teamListView(generics.ListAPIView):
search_fields = ['teamtranslation_team__team_name']
filter_backends = (filters.SearchFilter,)
serializer_class = teamSerializer
pagination_class = StandardResultsSetPagination

def get_queryset(self):
    accessor_id = self.request.user.id
    queryset = Team.objects.filter(is_active=True).order_by("id")
    return queryset

def post(self, request, *args, **kwargs):
    return self.list(request, *args, **kwargs)

def get_serializer_context(self):
    lang_id = UserProfile.objects.get(user_id=self.request.user.id).languages_id
    return {"lang_id": lang_id}

And this is serializer...

class teamSerializer(serializers.ModelSerializer):
team_id = serializers.IntegerField(source='id')
members_count = serializers.SerializerMethodField()
team_description = serializers.SerializerMethodField()
team_name = serializers.SerializerMethodField()
company_code = serializers.CharField(source='company.company_code')

def get_team_description(self, obj):
    lang_id = self.context.get('lang_id')
    if TeamTranslation.objects.filter(team_id=obj.id, languages_id=lang_id, is_active=True):
        return f'{TeamTranslation.objects.get(team_id=obj.id, languages_id=lang_id, is_active=True).team_description}'
    return f'{""}'

def get_team_name(self, obj):
    lang_id = self.context.get('lang_id')
    if TeamTranslation.objects.filter(team_id=obj.id, languages_id=lang_id, is_active=True):
        return f'{TeamTranslation.objects.get(team_id=obj.id, languages_id=lang_id, is_active=True).team_name}'
    return f'{""}'

def get_members_count(self, obj):
    return len(obj.user.values_list('id', flat=True))


class Meta:
    model = Team
    fields = ("team_id", "team_name", "team_description", 'members_count', 'company_id', 'company_code', 'has_user')

I try to order my data according to query parameter comes from request. So there is no problem when use order_by clause for Team model fields. The problem starts when try to order TeamTranslation fields. I want to order my serializer data before ListAPIView response it. Is there any way to do it?

I try using order_by clause to do that for example. queryset = queryset.order_by("teamtranslation_team__team_name")

or for reverse I use - sign. It works but I want to query parameter comes with field name that I describe in serializer fields. Because of that I think the best way can be order data in serializer data but I can't reach it. Order data by members count is also another problem. Thanks for your help.

Answers(1) :

You can look into OrderingFilter which allows you to order the queryset. Like this:

class teamListView(generics.ListAPIView):
    search_fields = ['teamtranslation_team__team_name']
    ordering_fields = ['id', 'teamtranslation_team__team_name']
    ordering = ['id']
    filter_backends = (filters.SearchFilter,filters.OrderingFilter)
    serializer_class = teamSerializer
    pagination_class = StandardResultsSetPagination
    queryset = Team.objects.filter(is_active=True)
    # no need to override get_queryset method
Comments:
2023-01-19 00:55:11
Thank for your answer. I don't want to use get query params value as "teamtranslation_team__team_name". I want to get it as team_name as in serializer fields. In assition it doesn't work with members_count field.