【问题标题】:can we modify value in django queryset using Django "F" expression . Query optimisation我们可以使用 Django "F" 表达式修改 django 查询集中的值吗?查询优化
【发布时间】:2021-05-31 05:33:57
【问题描述】:
now = datetime.utcnow().replace(tzinfo=utc)
    
.annotate(
        age=F(int((now - 'ended_at').total_seconds() / (60 * 60)))

我想在 Django 查询中添加上述逻辑。 基本上我想计算“年龄”,这是需要执行 ORM 操作的原因。 如果我使用 for 循环执行此操作,则数据量很大并且需要时间。

【问题讨论】:

    标签: django-2.0


    【解决方案1】:

    首先定义一个Func 以提取自 UNIX 纪元以来的秒数。

    from django.db.models import Func, IntegerField
    
    class UnixTime (Func):
        """
        Extract the number of seconds since January 1, 1970.
        """
    
        arity = 1
        output_field = IntegerField()
    
        # for PostgreSQL
        def as_sql(self, compiler, connection, **extra_context):
            return super().as_sql(
                compiler, connection,
                template="EXTRACT(EPOCH FROM %(expressions)s)",
                **extra_context)
    
        def as_mysql(self, compiler, connection, **extra_context):
            return super().as_sql(
                compiler, connection,
                template="UNIX_TIMESTAMP(%(expressions)s)",
                **extra_context)
    
        def as_sqlite(self, compiler, connection, **extra_context):
            return super().as_sql(
                compiler, connection,
                template="CAST(strftime('%%%%s', %(expressions)s) AS INTEGER)",
                **extra_context)
    

    然后进行这样的查询:

    from django.db.models import F
    from django.db.models.functions import Now
    
    YourObject.objects.annotate(
        age=(UnixTime(Now()) - UnixTime(F('ended_at'))) / 3600
    )
    

    【讨论】:

    • 我正在使用mysql
    • as_mysql 用于 MySQL
    猜你喜欢
    • 2019-07-21
    • 2018-11-08
    • 1970-01-01
    • 2011-10-17
    • 1970-01-01
    • 1970-01-01
    • 2019-05-03
    • 2017-12-26
    • 2021-11-10
    相关资源
    最近更新 更多