簡體   English   中英

我需要將原始MySQL查詢轉換為Django ORM查詢

[英]I need to convert raw MySQL query to Django ORM query

我有表示以下內容的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';

看看Subquery的Django文檔。 鏈接

簡而言之,這就是您想要的:

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')

嘗試這個。 我已對此代碼進行了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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM