rest_framework 自定义 order_by

rest_framework custom order_by

看看我能不能把问题问对?

model.py

class Point(models.Model):

    name = models.CharField(
        "nome del sistema",
        max_length=128,
    )
    x = models.FloatField(
        "cordinata spaziale x",
    )
    y = models.FloatField(
        "cordinata spaziale y",
    )
    z = models.FloatField(
        "cordinata spaziale z",
    )
    distance = float(0)

    
    def __str__(self) -> str:
        return f"{self.name}"

    @property
    def get_distance(self):
        return self.distance

    @get_distance.setter
    def get_distance(self, point):
        """
        ritorna la distanza che ce tra due sistemi
        """
        ad = float((point.x-self.x) if point.x > self.x else (self.x-point.x))
        bc = float((point.y-self.y) if  point.y > self.y else (self.y- point.y))
        af = float((point.z-self.z) if point.z > self.z else (self.z-point.z))
        return (pow(ad,2)+pow(bc,2)+pow(af,2))**(1/2)

    class Meta:
        verbose_name = "point"
        verbose_name_plural = "points"

在特定模型中有两个 defs 计算、保存和 return 相对于我们通过它们的点的距离

wenws.py

class PointViewset(viewsets.ModelViewSet):
    """
    modelo generico per un systema
    """
    queryset = Point.objects.all()
    serializer_class = PointSerializers
    filterset_class = PointFilter

在 wenws 中没有那么特别的解释和基础我们唯一要说的是作为过滤器我使用 'django_filters'

filters.py

import django_filters as filters
import Point

class CustomOrderFilter(filters.CharFilter):

    def filter(self, qs:QuerySet, value):
        if value in ([], (), {}, '', None):
            return qs
        try:
            base =  qs.get(name=value)
            for point in qs:
                point.get_distance = base
            qs = sorted(qs, key= lambda x: x.get_distance)  
        except Point.DoesNotExist:
            qs = qs.none()
        return qs


class PointFilter(filters.rest_framework.FilterSet):

    security = filters.ChoiceFilter(choices=security_choices
    point= CustomCharFilter(
        label = "point"
    )

    class Meta:
        model = Point
        fields = {
            'name':['exact'],
        }  

现在 'CustomCharFilter' 的复杂事情我在 http 请求中传递了系统的名称,然后 return 在我检查它不为空之后在过滤器中将其作为值发送给我并且我从 return 开始,我已经通过 base = qs.get ( name = value) 然后使用 point.get_distance = base '' on the inside of the for, at the end I reorder the QuerySet with qs = sorted (qs, key = lambda x: x.get_distance) 计算并保存每个点的距离 '' 这种方式和我尝试过的另一种方式的问题QuerySet 它 'transforms' 到一个列表中,这不适合我,因为我必须按照我想要的顺序 return 一个 QuerySet。我不知道该怎么做,因为 order_by 我不能使用它,因为距离不在数据库内 有人可以帮我吗?

所以问题是你想从 python 函数中过滤,这不能在查询中完成,因为它们只会说 SQL.

简单而缓慢的解决方案是在 python 中进行过滤,如果只有几个点,这可能会奏效。

points = list(Point.objects.all())
points.sort(cmp=comparison_function)

真正的解决方案是将该数学移植到 Djangos ORM 并用到给定点的距离注释您的查询集,这是一个非常高级的查询,如果您告诉我们您使用的数据库服务器,我们可能会帮助您还有那个。

ps。 python中有一个abs()函数来获取绝对值,而不是get_distance

中的if/else