how to sort the drf Django Custom Integer Field in serializer

24 Views Asked by At

I have a code here which has a custom column in serializer with a query of a count and sum.

class PersonListSerializer(serializers.ModelSerializer):
    org = OrgSerializer(many=False)   
    custom_fields = PersonCustomFieldValueSerializer(many=True)

    tags = TagSerializer(many=True, default=[])
    total_click_count = serializers.IntegerField(read_only=True)
    total_opened = serializers.IntegerField(read_only=True)
    total_reply = serializers.IntegerField(read_only=True)
    total_email_sent = serializers.IntegerField(read_only=True)
    scheduled_emails = serializers.SerializerMethodField()

    class Meta:
        model = Person
        fields = [
            "id",
            "first_name",
            "last_name",
            "job_title",
            "company_name",
            "work_email",
            "company_website",
            "sent_emails",
            "last_contacted",
            "next_scheduled_email",
            "custom_fields",
            "org",
            "tags",
            "total_click_count",
            "total_opened",
            "total_reply",
            "total_email_sent",
            "got_data",
            "force_enable",
            "assigned_user",
            "status",
            "person_city",
            "state",
            "industry",
            "phone",
            "linkedin",
            "scheduled_emails",
        ]

    def get_scheduled_emails(self, obj):
        return EmailSerializer(obj.get_scheduled_emails(), many=True).data

    def get_user_created_emails(self, _obj):
        return _obj.emails.filter(created_by=self.context["request"].user)
    
    def to_representation(self, obj):
        representation = super().to_representation(obj)

        # Calculate sent_email_count
        sent_email_count = obj.emails.filter(
            status=0, created_by=self.context["request"].user
        ).count()

        total_click_count = sum(
            click_count or 0
            for email in self.get_user_created_emails(obj)
            for click_count in email.click_tracking.values_list(
                "click_count", flat=True
            )
        )

        opened_emails = [
            email
            for email in self.get_user_created_emails(obj)
            if hasattr(email, "trackings") and email.trackings.opened
        ]

        total_reply_count = (
            self.get_user_created_emails(obj).aggregate(
                total_reply_count=Sum("reply_count__count")
            )["total_reply_count"]
            or 0
        )

        # Update the total_email_sent field in the representation
        representation['total_email_sent'] = sent_email_count
        representation['total_click_count'] = total_click_count
        representation['total_opened'] = len(opened_emails)
        representation['total_reply_count'] = total_reply_count

        return representation 

My fields with custom queries are :

representation['total_email_sent'] = sent_email_count
 representation['total_click_count'] = total_click_count
 representation['total_opened'] = len(opened_emails)
 representation['total_reply_count'] = total_reply_count

now How can i sort them with my modelviewset if an api request comes ?

Here is what i've tried but it gives me error that the columns is not present in my sorting field.

class PersonViewSet(ModelViewSet):    
    search_fields = [
        "first_name",
        "last_name",
        "job_title",
        "company_website",
        "industry",
        "work_email",        
        "person_city",
        "state",
        "email_domain",
        "linkedin",
        "got_data",
        "org__industry",
        "org__name",
        "org__domain",        
        "assigned_user",
    ]
    filter_backends = (
        filters.SearchFilter,
        filters.OrderingFilter,
        # CustomOrderingFilter,
        DjangoFilterBackend,
    )
    ordering_fields = [
        "first_name",
        "got_data",
        "assigned_user",
        "job_title",
        "company_name",
        "company_website",
        "industry",
        "work_email",
        "sent_emails",
        "org__name",        
        "last_contacted",
        "next_scheduled_email",
        "total_click_count",
        "total_opened",
        "total_reply_count",
        "total_email_sent",
    ]
    filterset_class = PersonFilter
    queryset = Person.objects.all()

    def create(self, request, *args, **kwargs):
        # Check if a user with the same email already exists
        user = request.user
        existing_user = Person.objects.filter(
            work_email=request.data.get("work_email"),
            team_id=user.team,
        ).first()
        if existing_user:
            return Response(
                {
                    "detail": "A person with this email already exists for this user's team."
                },
                status=status.HTTP_400_BAD_REQUEST,
            )

        return super().create(request, *args, **kwargs)

    def get_queryset(self, *args, **kwargs):

        if self.request.user.team:
            queryset = self.request.user.team.leads.all()
        else:
            queryset = super().get_queryset(*args, **kwargs)
                   
        return queryset
0

There are 0 best solutions below