具有动态半径的Django过滤器位置距离

时间:2019-10-09 16:43:04

标签: python django orm geodjango

我在django的一个区域和一家商店有2个模型,模型是这样的:

from django.contrib.gis.db import models
from django.contrib.gis.geos import Point
from django.contrib.gis.measure import D
from location_field.models.spatial import LocationField


class Zone(models.Model):
    name = models.CharField(max_length=200)
    location_point = LocationField(based_fields=['city'], zoom=7, default=Point(51.67, 32.65))
    radius = models.IntegerField(default=1000)  # radius in meters

class Shop(models.Model):
    name = models.CharField(max_length=200)
    location_point = LocationField(based_fields=['city'], zoom=7, default=Point(51.67, 32.65), null=True, blank=True)
    zone = models.ForeignKey(Zone, on_delete=models.CASCADE, null=True)

LocationField是在Django管理员中具有更好地图的PointField。

我要在每个商店中根据商店位置,区域位置和半径自动选择区域。如果没有半径要支持车间的区域,则将为“无”。我尝试了以下查询:

zone_list = Zone.objects.filter(
    location_point__distance_lte=(
        shop.location_point, D(m=models.F('radius'))
    )
)

但是我得到这个错误:

  

TypeError:float()参数必须是字符串或数字,而不是'F'

我该如何解决?

1 个答案:

答案 0 :(得分:1)

显然以前的方法无效!

这似乎发生在MeasureBase(继承自Distance/Ddjango.contrib.gis.measure类内部,更具体地讲,是in the default_units method在它尝试转换strfloat的数字输入值,但接收到F表达式。

我们可以作为一种解决方法,annotate Distance 请谨慎使用此Distance方法,因为它来自GeoDjango地理数据库函数< / em> )与当前shop.location_point之间的距离,然后我们可以按距离实例location_point的距离<=过滤该距离:

radius

对@ e4c5的出色回答表示敬意:GeoDjango filter by distance from a model field

另一种方法是完全消除from django.contrib.gis.db.models.functions import Distance zone_list = Zone.objects.annotate( distance=Distance('location_point', shop.location_point) ).filter(distance__lte=F('radius')) 部分,然后直接进行annotation的过滤:

Distance


我在此保留评论的连续性:

您可以尝试使用Cast()方法将from django.contrib.gis.db.models.functions import Distance zone_list = Zone.objects.filter( radius_gte=Distance('location_point', shop.location_point) ) 的结果强制转换为F('radius'),以将Integer转换为Float。

< s>
FloatField()