【问题标题】:Django Tastypie: filter results for a GET call by looping over model.objects.all()Django Tastypie:通过遍历 model.objects.all() 过滤 GET 调用的结果
【发布时间】:2015-11-05 05:19:04
【问题描述】:

我想使用 Tastypie 构建一个 API,该 API 接受一个纬度/经度对,然后在我的数据库中搜索其位置在该纬度/经度的给定距离内的所有条目。为此,我的模型有一个方法可以接收一个纬度/经度对,并返回从它自己的纬度/经度到给定纬度/经度的距离。

换句话说,我不想通过模型字段进行过滤,而是通过以下方式进行过滤:

latitude = # somehow get from Tastypie request
longitude = # somehow get from Tastypie request
distance = 80
all_models = Example.objects.all()
within_range = []
for model in all_models:
    distance_to_model = model.calculate_distance(latitude, longitude)
    if distance_to_model <= 80:
        within_range.append(model.name)
# somehow return within_range to Tastypie

我仔细阅读了文档,老实说有点不知所措——这是我将构建的第一个 API,看起来这个功能应该很容易找到,但我正在努力。

【问题讨论】:

    标签: python django tastypie


    【解决方案1】:

    首先你应该重新考虑你真的想要像 Tastypie 那样的 RESTful 类型的 API。因为拥有这种类型的接口是超级通用的,可以轻松快速地将您的数据公开给某些前端客户端,但需要您遵守不适合您当前问题的规则。

    如果我理解正确,您只想为这个计算构建一个 API 端点。如果是的话,这不是您使用 RESTful 类型 API 的情况。

    我建议你构建简单的 JSON 视图:

    @csrf_exempt
    def calculate_distance(request):
        # Pass data in various ways
        latitude = request.GET.get('latitude') or request.POST.get('latitude')
        longitude = request.GET.get('longitude') or request.POST.get('longitude')
    
        # Or pass data as JSON in request body
        if request.method != 'POST':
            return HttpResponseNotAllowed(permitted_methods=('POST',))
        try:
            data = json.loads(request.body)
        except (AttributeError, ValueError):
            return HttpResponseBadRequest(json.dumps({'message': 'json format incorrect'}),
                                          content_type='application/json')
        if data.get('latitude', None) and data.get('longitude', None):
            within_range = []
            for location in Location.objects.all():
                distance_to_model = location.calculate_distance(data['latitude'], data['longitude'])
                if distance_to_model <= 80:
                    within_range.append(location.name)
    
            return HttpResponse(json.dumps({'success': True,
                                            'within_range': within_range}),
                                content_type='application/json')
        else:
            return HttpResponseBadRequest(json.dumps({'message': 'offer_id is missing'}),
                                          content_type='application/json')
    

    您可以通过更多验证、授权、身份验证等来升级此视图。

    已编辑:

    但是,如果您出于某些原因决定坚持使用 Tastypie,请在模型资源类中使用 build_filters 方法:

    def build_filters(self, filters=None):
        if filters is None:
            filters = {}
    
        orm_filters = super(OfferResource, self).build_filters(filters)
        if 'pk__in' not in orm_filters:
            orm_filters['pk__in'] = []
    
        if 'latitude' in filters and 'longitude' in filters:
            for entity in Example.objects.all():
                distance_to_model = entity.calculate_distance(
                    filters['latitude'], filters['longitude'])
                if distance_to_model <= 80:
                    orm_filters['pk__in'].append(entity.pk)
    
        return orm_filters
    

    现在可以请求您的资源 ?latitude=xxx&longitude=yyyy。请记住,过滤器传递的值始终是字符串。确保 calculate_distance 可以处理它们。

    【讨论】:

    • 非常感谢您的回复!超级有帮助。我想我应该回去重新考虑我想用我的 API 做什么......现在这是我想要的唯一端点,所以我想我应该删除 Tastypie,直到我真的需要一些 RESTful 的东西。
    猜你喜欢
    • 2018-08-14
    • 2013-01-03
    • 2018-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-24
    相关资源
    最近更新 更多