[英]Django Rest how to order on a model method
Using Django Rest Framework is it possible to order
on a model method? 使用Django Rest Framework是否可以对模型方法进行
order
? I have tried it and DRF requires it to be field. 我已经尝试过了,DRF要求它必须在现场。 So gives the error:
因此给出错误:
Cannot resolve keyword 'distance' into field.
无法将关键字“距离”解析为字段。
View class ActivityListView(ListCreateView): 查看类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). 我认为答案是否定的,
OrderingFilter
可帮助您生成queryset(本质上是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. 但是通过模型方法进行排序意味着django需要将所有记录从数据库加载到内存中,然后在内存中对其进行排序。
If you have a amount of records there, your scrips will extremely slow. 如果那里有大量记录,则您的笔录将非常慢。
can you implement it in a SQL function? 可以在SQL函数中实现它吗? so that you can annotate the value by SQL function, then order by it.
这样您就可以通过SQL函数注释该值,然后对其进行排序。
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: 并且不要忘记创建sql函数,这是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;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.