Reputation: 159
I have a list of books with pincode of the location it was added from. I am getting a post request with pincode of user who wants to get such list. The list needs to be sorted according to the distance from the user.
Although I have a function to calculate the distance, I want to return a dynamic field named 'distance' in response.
My Book models is like:-
class Book(TimestampedModel):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,
null=True
)
name = models.CharField(max_length=20, blank=True)
desc = models.CharField(max_length=140, blank=True)
is_active = models.BooleanField(default=True, blank=False)
price = models.IntegerField(null=True)
pincode = models.IntegerField(null=False)
My serializer is like:-
class BookSerializer(serializers.ModelSerializer):
"""Serializer for book object"""
class Meta:
model = Book
fields = ('id', 'user', 'name', 'desc', 'is_active', 'sold_to', 'is_sold',
'age', 'price', 'created_at', 'updated_at', 'pincode')
and my view looks like:-
class BookViewSet(viewsets.ModelViewSet):
serializer_class = serializers.BookSerializer
queryset = Book.objects.all()
query_params = self.request.query_params
def get_queryset(self):
queryset = Book.objects.all()
if('pincode' in query_params):
pincode = query_params['pincode']
try:
for counter, instance in enumerate(queryset):
instance.distance = dist.query_postal_code(
pincode, instance.pincode)
queryset = sorted(queryset, key=attrgetter('distance'))
except Exception as ex:
print(ex)
return queryset
As you can see, I am able to calculate the distance in the view, I am not sure how to send this in response.
Please help me I will definitely help you some day :P
Upvotes: 0
Views: 1270
Reputation: 159
Finally, I have managed to do return a custom field. Following changes were made to my view and serializer.
Passing user's pincode (request's contextual info) to my serializer through context in serializer
def list(self, request):
queryset = self.get_queryset()
serializer = serializers.BookDetailSerializer(
queryset, context={'query_params': request.query_params}, many=True)
return Response(serializer.data)
Accessed Pincode through the passed context in distance function defined in serialzer:-
pincode = self.context['query_params']['pincode']
PS - Thanks Reshab Das for giving some directions
Upvotes: 0
Reputation: 170
Use this code in serializer:
class BookSerializer(serializers.ModelSerializer):
distance = serializers. SerializerMethodField()
@property
def get_query_pincode(self):
return self.context['request'].query_params.get('pincode', None)
def get_distance(self, obj):
if self.get_query_pincode:
# Your distance calcualting code here
return distance
return None
Next in the Meta
class:
class Meta:
model = Book
fields = ('id', 'user', 'name', 'desc', 'is_active', 'sold_to', 'is_sold',
'age', 'price', 'created_at', 'updated_at', 'pincode', 'distance')
You will need to add the new field in fields
attribute and since its not an actual model field, SerializerMethodField
is read only field.
Hope this helps!
Upvotes: 2