【问题标题】:How to annotate JSON fields in Django?如何在 Django 中注释 JSON 字段?
【发布时间】:2020-07-22 15:10:35
【问题描述】:

我有一个这样的模型:

class MyModel(models.Model):
    details = models.JSONField()
    # other fields

我想像这样注释这个模型的一些字段:

qs = MyModel.objects.filter(id__in=given_list).annotate(
         first_name=F('details__first_name'),
         last_name=F('details__last_name')
     )

但是F() 表达式没有考虑 json 键,它只返回详细信息字段。

我使用的是 MySQL,所以不能使用KeyTextTransform

我尝试像这样使用 RawSQL:

qs = MyModel.objects.filter(id__in=given_list).annotate(
         first_name=RawSQL("(details->%s)", ('first_name',)),
         last_name=RawSQL("(details->%s)", ('last_name',))
     )

但它给出了这个错误:

MySQLdb._exceptions.OperationalError: (3143, 'Invalid JSON path expression. The error is around character position 1.')

那么我该怎么做才能让一切按预期进行呢?

【问题讨论】:

    标签: mysql django


    【解决方案1】:

    可以使用JSONExtract,写起来更容易理解:

    from django_mysql.models.functions import JSONExtract
    qs = MyModel.objects.filter(id__in=given_list).annotate(
             first_name=JSONExtract('details', '$.first_name'),
             last_name=JSONExtract('details', '$.last_name')
         )
    

    【讨论】:

      【解决方案2】:

      MySQL json extractions 有一个使用jsonfield->"$.key" 的特殊语法。试试这个:

      qs = MyModel.objects.filter(id__in=given_list).annotate(
          first_name=RawSQL("(details->%s)", ('$.first_name',)),
          last_name=RawSQL("(details->%s)", ('$.last_name',))
      )
      

      【讨论】:

      • MySQLdb._exceptions.ProgrammingError: (1064, "您的 SQL 语法有错误;请查看与您的 MySQL 服务器版本相对应的手册,以了解在 'first_name' 附近使用的正确语法)) AS first_name, ((proxy_details->'$.'last_name'')) AS `las' at line 1")
      • 现在试试,我忘了 django 引用了参数
      【解决方案3】:

      您可以将属性添加到您的MyModel 并让它们返回相应的信息

      class MyModel(models.Model):
          details = models.JSONField()
          
          @property
          def first_name(self):
              return self.details['first_name']
          @property    
          def last_name(self):
              return self.details['last_name']
      

      【讨论】:

        猜你喜欢
        • 2017-06-26
        • 2019-01-22
        • 2023-01-27
        • 2014-05-18
        • 2019-07-21
        • 1970-01-01
        • 2019-09-03
        • 2013-10-30
        • 2020-11-03
        相关资源
        最近更新 更多