使用 JSONField 中的列表在 Django 中查找对象

Posted

技术标签:

【中文标题】使用 JSONField 中的列表在 Django 中查找对象【英文标题】:Find an object in Django using a list inside JSONField 【发布时间】:2021-02-18 16:04:13 【问题描述】:

我在Django有这样一个模型:

class Event(models.Model):                                                                                                 
    EVENT_TYPE_CHOICES = [(e, e.value) for e in EVENT_TYPE]                                                                
    event_type = models.TextField(choices=EVENT_TYPE_CHOICES)                                                              
                                                                                                                           
    date_of_event = models.DateTimeField(default=timezone.now, db_index=True)                                              
    event_data = JSONField()

还有event_dataJSONField,其结构如下:

    'project_id': project_id,                                                                                       
    'family_id': family_id,                                                                                         
    'variant_data': variant_data_list,                                                                              
    'username': user.username,                                                                                      
    'email': user.email, 

其中variant_data_list 是具有3 str 值的dict 对象的列表:

'xpos': xpos, 'ref': ref, 'alt': alt

现在,我需要一种方法来根据提供的variant_data_list 找到唯一的Event 模型对象(其中的每个对象都应该在单个Events'variant_data_list 中找到,是否可以实现不知何故?variant_data_list 中的项目数从13

否则我正在考虑在每次写入postgres 时根据variant_data_list 生成唯一ID(但也不知道如何制作)。任何建议将不胜感激。

【问题讨论】:

【参考方案1】:

您可能能够按照此答案 (Django JSONField filtering) 中的说明过滤 json 字段 - 以下内容未经测试:

# filter for events with a specific variant_data list:
Event.objects.filter(event_data__variant_data=[<the list>])

# filter for events with specific items in the variant data list:
Event.objects.filter(
    event_data__variant_data__contains='item1', 
    event_data__variant_data__contains='item2',
    ...
)

您可以通过遍历所有可能效率较低的事件来获取对象列表:

events = [
    event for event in Event.objects.all() if event.event_data['variant_data'] == [<the list>]
]

您还可以按照您的建议覆盖事件的保存方法:

class Event(...):

    variant_data_id = models.CharField(...)
  
    ...
   
    def save(self, *args, **kwargs):

        self.variant_data_id = some_hash_method(self.event_data['variant_list']

        super(Event, self).save(*args, **kwargs)

【讨论】:

我不知道如何正确使用散列来实现它,这样就不会发生冲突。第一种方法可能不起作用,因为列表中对象的顺序可能不同,但顺序应该无关紧要。 好吧,variant_data_id 字段本身不需要是唯一的,但也许您希望它...您可以更改查询以使用 @987654325 来说明列表中项目的顺序@ - 查看编辑。

以上是关于使用 JSONField 中的列表在 Django 中查找对象的主要内容,如果未能解决你的问题,请参考以下文章

Django:在过滤器和搜索中使用 JSONField 属性

ArrayField 中的 Django JSONField

Django中的JSONField即使在POST请求后仍保持为空

如何在具有 Jsonfield 的模型中发布 django rest 中的数据

Django save request.POST to JSONField 从列表中选择最后一项而不是保存列表

django 无法访问模板中的 jsonfield 数据