如何创建具有多个过滤器的Django数据库查询?

时间:2014-12-08 18:14:47

标签: python json django http

我有一个艺术家和绘画数据库,我想根据艺术家姓名和绘画标题进行查询。标题位于json文件中(艺术家名称来自ajax),所以我尝试了一个循环。

def rest(request):

    data = json.loads(request.body)
    artistname = data['artiste']
    with open('/static/top_paintings.json', 'r') as fb:
        top_paintings_dict = json.load(fb)

    response_data = []

    for painting in top_paintings_dict[artist_name]:
        filterargs = {'artist__contains': artistname, 'title__contains': painting}  
        response_data.append(serializers.serialize('json', Art.objects.filter(**filterargs)))

    return HttpResponse(json.dumps(response_data), content_type="application/json")

它不会返回我需要的对象列表,只是一些丑陋的双序列化json数据对任何人都没有好处。

   ["[{\"fields\": {\"artist\": \"Leonardo da Vinci\", \"link\": \"https://trove2.storage.googleapis.com/leonardo-da-vinci/the-madonna-of-the-carnation.jpg\", \"title\": \"The Madonna of the Carnation\"}, \"model\": \"serve.art\", \"pk\": 63091}]",

这个处理程序可以工作并返回我为艺术家绘制的每一幅画。

def rest(request):

    data = json.loads(request.body)
    artistname = data['artiste']
    response_data = serializers.serialize("json", Art.objects.filter(artist__contains=artistname))
    return HttpResponse(json.dumps(response_data), content_type="application/json")

我只需按标题和艺术家过滤我的查询。

2 个答案:

答案 0 :(得分:2)

inYour问题是您要将数据序列化为json两次 - 一次使用serializers.serialize,然后再使用json.dumps

我不知道你的应用程序的细节,但可以在django中链接过滤器。所以我会采用你的第二种方法,只需更换一行

response_data = serializers.serialize("json", Art.objects.filter(artist__contains=artistname))

response_data = serializers.serialize("json", Art.objects.filter(artist__contains=artistname).filter(title__in=paintings))

检查queryset documentation

答案 1 :(得分:2)

__contains搜索绘画标题执行此操作的最有效方法是将Q objectsor一起使用所有可能的绘画名称:

from operator import or_

def rest(request):

    data = json.loads(request.body)
    artistname = data['artiste']
    with open('/static/top_paintings.json', 'r') as fb:
        top_paintings_dict = json.load(fb)

    title_filters = reduce(or_, (Q(title__contains=painting) for painting in top_paintings_dict[artist_name]))
    paintings = Art.objects.filter(title_filters, artist__contains=artist_name)

那将为您提供一系列绘画。我怀疑你的双序列化是不正确的,但似乎你对单个艺术家名称的情况感到满意,所以我会把它留给你。

此处reduce调用是一种将|多个Q个对象构建在一起的结果的方法 - operator.or_|的功能句柄,然后我使用生成器表达式为每个绘画名称创建一个Q对象。