Reputation: 2123
My goal is to retrieve a dictionary where the key is the id of a target group object, and the value is the corresponding target group object.
Additionally I want a custom field "enabled" which represents whether the target_group is paired to the given category (cat_id).
The url would be for example:
http://localhost:8000/api/ctg/?cat_id=61
Example of resulting dictionary:
{
1: {
id: 1,
name: "target group name",
employer: 175,
enabled: false,
},
5: {
id: 5,
name: "another target group name",
employer: 175,
enabled: true,
},
...
}
The way I do it currently:
Obviously this is very inefficient and requires 2 calls to the database.
If possible I would like to retrieve the dictionary which I can use right away in my front end. I have been searching for solutions but I can't really find much about DRF beyond the basics... could someone point me in the right direction as to how to achieve this?
ViewSets:
# get all target groups
class TargetGroupViewset(viewsets.ModelViewSet):
queryset = TargetGroup.objects.all()
serializer_class = TargetGroupSerializer
def list(self, request):
queryset = TargetGroup.objects.filter(employer=self.request.user.pk)
serializer = TargetGroupSerializer(queryset, many=True)
return Response(serializer.data)
# get target groups which are connected to a given category
class GetTargetGroupsForCategory(viewsets.ModelViewSet):
queryset = TargetGroup.objects.all()
serializer_class = TargetGroupSerializer
def list(self, request):
queryset = TargetGroup.objects.filter(employer=self.request.user.pk)
if request.query_params:
cat_id = request.query_params['cat_id']
ctg_ids = list(CategoryTargetGroup.objects.filter(category=cat_id).values_list('target_group_id', flat=True))
queryset = TargetGroup.objects.filter(id__in=ctg_ids)
serializer = TargetGroupSerializer(queryset, many=True)
return Response(serializer.data)
Models
# target group model
class TargetGroup(models.Model):
employer = models.ForeignKey(CustomUser, on_delete=models.CASCADE, null=False)
name = models.CharField(max_length=255, blank=False, null=False)
# category-targetgroup model
class CategoryTargetGroup(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE, null=False)
target_group = models.ForeignKey(TargetGroup, on_delete=models.CASCADE, null=False)
Upvotes: 0
Views: 504
Reputation: 1520
Currently your TargetGroupSerializer
returns this:
[
{
id: 1,
name: "target group name",
employer: 175,
enabled: false,
},
{
id: 5,
name: "another target group name",
employer: 175,
enabled: true,
},
...
]
In order to transform it to desired result, you could use a dict comprehension, like this:
def list(self, request):
...
result = {item['id']: item for item in serializer.data}
return Response(result)
As for the second part of the question, I don't think you need the GetTargetGroupsForCategory
viewset. To add a field enabled
, you can declare a SerializerMethodField in TargetGroupSerializer
:
class TargetGroupSerializer(serializers.ModelSerializer):
# your serializer fields + new `enabled` field
enabled = serializers.SerializerMethodField()
class Meta:
# your options
def get_enabled(self, obj):
return self.context['cat_id'] == obj.id
And finally pass the cat_id
to the serializer context in your TargetGroupViewset
:
def list(self, request):
queryset = TargetGroup.objects.filter(employer=self.request.user.pk)
cat_id = request.query_params.get('cat_id', None)
serializer = TargetGroupSerializer(queryset, many=True, context={'cat_id': cat_id})
result = {item['id']: item for item in serializer.data}
return Response(result)
Upvotes: 1