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