【问题标题】:Consuming JSON API data with Django使用 Django 使用 JSON API 数据
【发布时间】:2021-03-03 05:42:15
【问题描述】:

从 Django 应用程序中,我可以使用来自单独的 Restful API 的数据,但是过滤呢?下面返回所有书籍及其数据。但是,如果我只想按作者、日期等获取书籍怎么办?我想传递作者的姓名参数,例如.../authors-name 或 /?author=name 并仅返回 json 响应中的那些。这可能吗?

views.py

def get_books(request):
    response = requests.get('http://localhost:8090/book/list/').json()
    return render(request, 'books.html', {'response':response})

那么有没有办法像模型对象一样过滤?

【问题讨论】:

  • 我不知道任何在 Python 或 Django 中开箱即用的东西,用于过滤字典列表。您可以使用谓词函数调用filter,该函数对匹配的书返回true,否则返回false。
  • 动态构建谓词并不难,因此您可以编写一个与 Django 的QuerySet/Manager.filter 签名类似的函数,该函数根据关键字参数返回自定义谓词函数。
  • 我决定尝试实现这一点。
  • 另一个想法是尽可能利用您正在使用的 API 的过滤功能。

标签: json django api filtering


【解决方案1】:

我能想到三种方法:

  1. Python 的filter 可以与一些额外的代码一起使用。
  2. QueryableList,这是我见过的最接近 ORM 的列表。
  3. query-filter,采用更实用的方法。

1。内置过滤功能

您可以编写一个函数,该函数返回告诉您列表元素是否匹配的函数,并将生成的函数传递给filter

def filter_pred_factory(**kwargs):

    def predicate(item):
        for key, value in kwargs.items():

            if key not in item or item[key] != value:
                return False

        return True

    return predicate

def get_books(request):
    books_data = requests.get('http://localhost:8090/book/list/').json()
    pred = filter_pred_factory(**request.GET)
    data_filter = filter(pred, books_data)

    # data_filter is cast to a list as a precaution
    # because it is a filter object,
    # which can only be iterated through once before it's exhausted.
    filtered_data = list(data_filter)
    return render(request, 'books.html', {'books': filtered_data})

2。可查询列表

QueryableList 将实现与上述相同的功能,但具有一些额外的功能。除了/books?isbn=1933988673,您还可以使用/books?longDescription__icontains=linux 之类的查询。你可以找到其他功能here

from QueryableList import QueryableListDicts

def get_books(request):
    books_data = requests.get('http://localhost:8090/book/list/').json()
    queryable_books = QueryableListDicts(books_data)
    filtered_data = queryable_books.filter(**request.GET)
    return render(request, 'books.html', {'books':filtered_data})

3。查询过滤器

query-filter 有类似的features,但没有复制 ORM 的面向对象方法。

from query_filter import q_filter, q_items

def get_books(request):
    books_data = requests.get('http://localhost:8090/book/list/').json()
    data_filter = q_filter(books_data, q_items(**request.GET))

    # filtered_data is cast to a list as a precaution
    # because q_filter returns a filter object, 
    # which can only be iterated through once before it's exhausted.
    filtered_data = list(data_filter)
    return render(request, 'books.html', {'books': filtered_data})

值得一提的是我写了query-filter

【讨论】:

  • 感谢您的回复。一个多星期以来,我一直在为此挠头!特定的 API 没有参数,它只是一个列表。我确实考虑过将 api 数据转储到模型中,但后来我认为我让它变得比应该的更复杂。我是自学成才的,所以我需要一些时间来解开你的建议,但它给了我一些方向。一旦我有时间消化这个并做一些测试,我会做出回应。再次感谢您的回复!
  • 我在 GitHub 上找到了一些我认为你想要的东西:github.com/kata198/QueryableList
  • 这里也是 PiPy 链接:pypi.org/project/QueryableList
  • 如果它满足您的需求,我会更新我的答案。反正我的过滤想法还没有完全发展。
  • 嘿@Stubb207,希望你有一个愉快的假期(考虑到世界事件)。我已经更新了我的答案,所以希望现在更清楚了。如果能正确解决您的问题,我将不胜感激。
猜你喜欢
  • 2013-10-30
  • 2016-08-14
  • 2015-10-08
  • 2016-11-04
  • 1970-01-01
  • 1970-01-01
  • 2020-01-31
  • 2021-09-22
  • 1970-01-01
相关资源
最近更新 更多