【问题标题】:I need to convert raw MySQL query to Django ORM query我需要将原始 MySQL 查询转换为 Django ORM 查询
【发布时间】:2019-12-10 01:29:13
【问题描述】:

我有 models.py 代表如下:

from django.db import models
from django.db.models.signals import post_save

# Create your models here.
from django.http import request


class Task(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    description = models.CharField(max_length=512)
    cost = models.DecimalField(decimal_places=2, max_digits=8)

    def __str__(self):
        return self.description + "-" + str(self.cost)


class TaskStatus(models.Model):
    STATUS = (
        (0, 'Created'),
        (1, 'Taken'),
        (2, 'Reissued'),
        (3, 'On approve'),
        (4, 'Done'),
    )
    task_id = models.IntegerField()
    created = models.DateTimeField(auto_now_add=True)
    status = models.PositiveSmallIntegerField(choices=STATUS, default=0)

    def __str__(self):
        return str(self.task_id) + ' ' + str(self.status)

    def create_status(sender, instance, **kwargs):
        if kwargs['created']:
            task_status = TaskStatus.objects.create(task_id=instance.id)

    post_save.connect(create_status, sender=Task)

我必须将该 mysql 查询转换为 django ORM 查询。我在这上面堆了 2 天。请建议我一些有用的链接来了解如何执行。

SELECT t.created,
      t.description,
      (SELECT MAX(s.created)
       FROM task_statuses s
       WHERE s.task_id = t.id AND s.status_type = 3
       GROUP BY s.task_id) as task_on_approve
FROM task t
WHERE t.created BETWEEN '2019-04-01 00:00:00' AND '2019-04-30 23:59:59';

【问题讨论】:

    标签: python mysql django orm


    【解决方案1】:

    查看Subquery 的 Django 文档。 Link.

    简而言之,这就是您要查找的内容:

    from django.db import models
    
    Task.objects.filter(created__gte='2019-04-01', created__lt='2019-05-01').annotate(task_on_approve=models.Subquery(TaskStatus.objects.filter(task_id=models.OuterRef('id'), status_type=3).order_by('-created').values('created')[:1], output_field=models.DateTimeField())).values('created', 'description', 'task_on_approve')
    

    【讨论】:

      【解决方案2】:

      试试这个。 我测试了这段代码 100% 工作。

      from datetime import datetime
      from datetime import timezone
      
      from django.core.management.base import BaseCommand, CommandError
      from django.db.models import Avg, Max, Min, Sum, DateTimeField
      from django.db.models import OuterRef, Subquery
      
      from app.models import Task, TaskStatus
      
      class Command(BaseCommand):
          def handle(self, *args, **options):
      
              sub_query = TaskStatus.objects\
                  .annotate(max_created_date=Max('created'))\
                  .filter(\
                      task_id=OuterRef('pk'),
                      status=3
                  )
      
              from_datetime = datetime.strptime('2019-04-01 00:00:00', '%Y-%m-%d %H:%M:%S').replace(tzinfo=timezone.utc)
              to_datetime = datetime.strptime('2019-04-30 23:59:59', '%Y-%m-%d %H:%M:%S').replace(tzinfo=timezone.utc)
      
              query = Task.objects.annotate(
                  task_on_approve=Subquery(
                      sub_query.values('max_created_date')[:1],
                      output_field=DateTimeField()
                  )
              ).filter(
                  created__range=[
                      from_datetime,
                      to_datetime
                  ]
              )
      
              print(query.query)
      
              self.stdout.write('Done.')
      

      输出

      SELECT "app_task"."id", "app_task"."created", "app_task"."description", "app_task"."cost", (SELECT MAX(U0."created") AS "max_created_date" FROM "app_taskstatus" U0 WHERE (U0."status" = 3 AND U0."task_id" = ("app_task"."id")) GROUP BY U0."id", U0."task_id", U0."created", U0."status"  LIMIT 1) AS "task_on_approve" FROM "app_task" WHERE "app_task"."created" BETWEEN 2019-04-01 00:00:00 AND 2019-04-30 23:59:59
      

      【讨论】:

        猜你喜欢
        • 2022-08-18
        • 2019-06-11
        • 2016-06-04
        • 2020-07-13
        • 2015-08-23
        • 1970-01-01
        • 2016-04-27
        • 2016-04-20
        • 2018-05-15
        相关资源
        最近更新 更多