【问题标题】:Django custom manager to filter nearby through related modelDjango 自定义管理器通过相关模型过滤附近
【发布时间】:2018-05-01 03:11:38
【问题描述】:

我有两个型号ShopAddress

店铺Model:

class Shop(BaseModel):
    name = models.CharField(
        max_length=100,
        blank=True,
        null=True
    )
    address = models.ForeignKey(
        Address,
        blank=True,
        null=True,
        on_delete=models.SET_NULL
    )
    objects = LocationManager()

地址Model:

class Address(BaseModel):
    latitude = models.DecimalField(
        max_digits=16,
        decimal_places=14, 
        blank=True,
        null=True
    )
    longitude = models.DecimalField(
        max_digits=16,
        decimal_places=14, 
        blank=True,
        null=True
     )
     status = models.NullBooleanField(null=True)

我已经为 Shop 模型创建了一个自定义管理器

class LocationManager(models.Manager):
    def nearby(self, latitude, longitude, proximity):
        """
        Return all object which distance to specified coordinates
        is less than proximity given in kilometers
        """
        # Great circle distance formula
        # acos will not work in sqlite
        gcd = """
            6371 * acos(
                cos(radians(%s)) * cos(radians(latitude))
                * cos(radians(longitude) - radians(%s)) +
                sin(radians(%s)) * sin(radians(latitude))
            )
        """
        queryset =  self.get_queryset().select_related(
            'address'
        ).exclude(
            latitude=None
        )
        .exclude(
            longitude=None
        )
        .annotate(
            distance=RawSQL(
                gcd,
                (
                    latitude,
                    longitude,
                    latitude
                )
            )
        ).filter(
            distance__lt=proximity
        ).order_by('distance')

        return queryset

现在我想使用自定义管理器查找附近的商店:

Shop.objects.nearby(13.244334,72.329832,20)

但我收到此错误:

Cannot resolve keyword 'latitude' into field. Choices are: address, address_id, name

如何使用通过latitude 过滤我的查询集来查找附近的商店?

【问题讨论】:

    标签: django django-models django-orm django-managers


    【解决方案1】:

    您正在查询您的 Shop 模型,而不是您的 Address 模型。 正如您的错误所述,您的 Shop 模型没有任何名为 latitude 的字段。

    您应该使用字段查找通过链接对象Address (documentation) 的属性过滤您的Shops

    由于您的Shop 模型通过address 字段链接到您的Address 模型,因此要通过Address 属性过滤Shop,您可以执行以下操作(即对于latitude 字段):

    Shop.objects.filter(address__latitude=<your_lookup_here>)
    

    另外,您的两个exclude 方法可以这样重写(使用Q 对象):

    Shop.objects.exclude(
        Q(address__latitude__isnull=True)
        | Q(address__longitude__isnull=True)
    )
    

    我建议您阅读上面链接的有关查询集 API 的文档。

    【讨论】:

    • 在执行 select_related() django 内部会与相关表进行左外连接。我想使用地址表中的纬度和经度。
    • select_related 添加join子句,但仍需要使用relation查询相关实例属性。我强烈建议您阅读以下内容:docs.djangoproject.com/en/1.11/topics/db/queries/…
    猜你喜欢
    • 2017-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-22
    • 1970-01-01
    • 1970-01-01
    • 2018-07-15
    相关资源
    最近更新 更多