Using Django Rest Framework is it possible to order
on a model method? I have tried it and DRF requires it to be field. So gives the error:
Cannot resolve keyword 'distance' into field.
View class ActivityListView(ListCreateView):
queryset = model_activity.objects.all()
serializer_class = ActivityListSerializer
filter_backends = (OrderingFilter,)
# default ordering
ordering = ('distance')
Serializer
class ActivityListSerializer(serializers.ModelSerializer):
distance = serializers.SerializerMethodField('_get_distance')
class Meta:
model = model_activity
fields = ('id', 'distance')
def _get_distance(self, obj):
return obj.get_distance(user=self.context['request'].user)
I think the answer is no, the OrderingFilter
helps you to generate the queryset(essentially SQL).
but ordering by a model method means the django needs to load all the records from the database to the memory, then order it in the memory.
If you have a amount of records there, your scrips will extremely slow.
can you implement it in a SQL function? so that you can annotate the value by SQL function, then order by it.
from django.db import models
class ActivityListView(ListCreateView):
queryset = model_activity.objects.all()
serializer_class = ActivityListSerializer
filter_backends = (OrderingFilter,)
# default ordering
ordering = ('distance')
def filter_queryset(self, queryset):
cur_latitude, cur_longitude = self.get_cur_latitude_longitude()
# add the distance field to sql dataset result, so that we can order by it
queryset = queryset.annotate(
distance=models.Func(cur_latitude, cur_longitude, 'latitude', 'longitude', function='get_distance')
)
return super(ActivityListView, self).filter_queryset(self, queryset)
and don't forget to create the sql function, here's a example for postgresql:
CREATE OR REPLACE FUNCTION public.geodistance(alat float8, alng float8, blat float8, blng float8)
RETURNS float8
AS
$BODY$
SELECT
case when $1 is null or $2 is null or $3 is null or $4 is null
then 9999999
else
asin(
sqrt(
sin(radians($3-$1)/2)^2 +
sin(radians($4-$2)/2)^2 *
cos(radians($1)) *
cos(radians($3))
)
) * 7926.3352
end
AS distance;
$BODY$
LANGUAGE sql IMMUTABLE;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.