Django Postgres JSONField 查询

Arj*_*ngh 1 django postgresql python-3.x django-rest-framework

我有一个包含 json 字段的类

class A(models.Model)
    brand = JSONField()
Run Code Online (Sandbox Code Playgroud)

如果我发布像 [{'brand_id:1', 'name':'b1'}, {'brand_id:2', 'name':'b2'}] 这样的 JSON 数组,它会存储为 JSON 数组。这很好用。

我应该如何查询以检查该数组中任何字典的brand_id中是否存在“1”?

jhr*_*hrr 5

首先,您的 JSON 格式错误。我认为它的意思是:

[{'brand_id': 1, 'name': 'b1'}, {'brand_id': 2, 'name': 'b2'}] 
Run Code Online (Sandbox Code Playgroud)

如果是这种情况,要1在这样的 blob 中进行测试,类似这样的内容会告诉您是否可以在 JSON 中的任何位置1找到 s作为值:

def check_for_one(json_data):
    return any([1 in data.values() for data in json_data])
Run Code Online (Sandbox Code Playgroud)

但是您想具体了解JSON 中任何位置的1键是否拥有 s 值 ,因此您还可以使用循环来添加一些额外条件:brand_id

def check_for_one(json_data):
    match = []
    for data in json_data:
        for key, value in data.items():
            if key == 'brand_id' and value == 1:
                match.append(True)
    return any(match)
Run Code Online (Sandbox Code Playgroud)

您可以将此类逻辑作为方法合并到模型类中,如下所示:

class A(models.Model):
    brand = JSONField()

    def check_for_one_comprehension(self):
        return any([1 in data.values() for data in self.brand])

    def check_for_one_loop(self):
        match = []
        for data in self.brand:
            for key, value in data.items():
                if key == 'brand_id' and value == 1:
                    match.append(True)
        return any(match)
Run Code Online (Sandbox Code Playgroud)

但是,如果您确实想从数据库中过滤实例,其中 JSON 数据是顶层的数组brand_id == 1,则需要不同的方法,这应该可以做到:

A.objects.filter(brand__contains=[{'brand_id': 1}])
Run Code Online (Sandbox Code Playgroud)

注意额外的大[{}]括号!如果你只是调用contains=['brand_id': 1]它会抛出语法错误,如果你调用contains={'brand_id': 1}它会不匹配。