gpt4 book ai didi

Python TastyPie - 自定义管理器方法作为过滤器?

转载 作者:太空宇宙 更新时间:2023-11-03 15:23:18 24 4
gpt4 key购买 nike

我有一个 GeoDjango 项目,它有这样的管理器模型;

class AdvertManager(models.GeoManager):

def within_box(self, x0, y0, x1, y1):
geometry = Polygon.from_bbox((x0, y0, x1, y1,))
return self.filter(point__within=geometry)

我正在尝试让我的资源模型 (AdvertResource) 通过 GET 参数公开 within_box 函数,例如;

http://127.0.0.1:8000/api/v1/advert/?format=json&box=51.623349,-3.25362,51.514195,-3.4754133

我开始像这样在资源模型上写一个build_filters方法;

def build_filters(self, filters=None):
if not filters:
filters = {}
orm_filters = super(AdvertResource, self).build_filters(filters)

if 'box' in filters:
points = [float(p.strip()) for p in filters['box'].split(',')]
orm_filters = {'box': Advert.objects.within_box(*points).all()}

return orm_filters

但这会引发错误“无法将关键字‘box’解析为字段...”。

是否可以将方法从自定义管理器公开到 api url?

编辑 - 我现在已经使用以下解决方案解决了这个问题。

class AdvertResource(ModelResource):

longitude = fields.FloatField(attribute='longitude', default=0.0)
latitude = fields.FloatField(attribute='latitude', default=0.0)
author = fields.ForeignKey(UserResource, 'author')

def build_filters(self, filters=None):
"""
Build additional filters
"""
if not filters:
filters = {}
orm_filters = super(AdvertResource, self).build_filters(filters)

if 'point__within_box' in filters:
points = filters['point__within_box']
points = [float(p.strip()) for p in points.split(',')]
orm_filters['within_box'] = points

return orm_filters

def apply_filters(self, request, applicable_filters):
"""
Apply the filters
"""
if 'within_box' in applicable_filters:
area = applicable_filters.pop('within_box')
poly = Polygon.from_bbox(area)
applicable_filters['point__within'] = poly
return super(AdvertResource, self).apply_filters(request,
applicable_filters)

现在这意味着请求 http://127.0.0.1:8000/api/v1/advert/?format=json&point__within_box=51.623349,-3.25362,51.514195,-3.4754133 现在过滤所有结果在边界框内。

最佳答案

上面的代码有几个问题。

首先,是的,您可以将任何自定义管理器暴露给任何东西,无论您是否使用它。仅当您将其默认管理器替换为您自己的版本时,才能通过 Advert.objects 访问您在上面定义的 AdvertManager。

其次,您希望在 AdvertResource 上公开 tastypie 过滤的方式与过滤的实际工作方式正交。

所有过滤器都以 <field_name>__<filter_name>=<value_or_values> 的形式应用为实际上的 ORM 过滤器.因为在您的示例中您使用的是 box=<number>,<number>,...,<number> tastypie 将其分解为 box__exact=...并试图找到 box AdvertResource 中的字段并按预期失败。

如果您的广告有一个名为 location 的字段你可以添加withinbox作为该字段的过滤器并按以下条件过滤:location__withinbox=<values> .

如果您想保留原来的方法,则必须自己从 request.GET 字典中解析框过滤器,然后将它们传递给您自己的重写版本 obj_getobj_get_list在 AdvertResource 中。

最后,在扩展 build_filters 时您只是在 Tastypie 过滤器和 ORM 过滤器之间建立映射。在您的示例中,您将对象作为过滤器返回;而不是简单地将其定义为:

{ 'withinbox' : 'point__within' }

并将值列表转换为 Polygonapply_filters 内在它被移交给实际的过滤器方法之前。

关于Python TastyPie - 自定义管理器方法作为过滤器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11604045/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com