Django-cte дает: У объекта 'QuerySet' нет атрибута 'with_cte'

У меня есть записи в следующем формате:

| id  | name |       created                  |
-----------------------------------------------
|1    | A    |2024-04-10T02:49:47.327583-07:00|
|2    | A    |2024-04-01T02:49:47.327583-07:00|
|3    | A    |2024-03-01T02:49:47.327583-07:00|
|4    | A    |2024-02-01T02:49:47.327583-07:00|
|5    | B    |2024-02-01T02:49:47.327583-07:00|

Модель:

class Model1(model.Models):
   name = models.CharField(max_length=100)
   created = models.DateTimeField(auto_now_add=True)

Я хочу выполнить group by в django с месяцем из поля created и получить последнюю запись из этого месяца.

Ожидаемый результат:

| id  | name |       created                  |
-----------------------------------------------
|1    | A    |2024-04-10T02:49:47.327583-07:00|
|3    | A    |2024-03-01T02:49:47.327583-07:00|
|4    | A    |2024-02-01T02:49:47.327583-07:00|

Я использую django-cte для выполнения вышеуказанного действия

from django.db.models.functions import DenseRank, ExtractMonth
from django_cte import With
m = Model1.objects.get(id=1)
cte = With(
        Model1.objects.filter(name=m.name)
          rank=Window(
            expression=DenseRank(),
            partition_by=[ExtractMonth("created")],
            order_by=F("created").desc(),
        )
     )
qs = cte.queryset().with_cte(cte).filter(rank=1)

Но вышеуказанное дает ошибку:

qs = cte.queryset().with_cte(cte).filter(rank=1)
                    ^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'QuerySet' object has no attribute 'with_cte'

Помогите, пожалуйста!

Вам нужно смешать CTEManager, иначе получится "ваниль" QuerySet:

from django_cte import CTEManager


class Model1(model.Models):
    name = models.CharField(max_length=100)
    created = models.DateTimeField(auto_now_add=True)
    objects = CTEManager()

Вы также можете явно определить CTE в запросе.

Сначала аннотируйте каждую запись месяцем, извлеченным из поля created, и проранжируйте их внутри каждого месяца с помощью функции DenseRank(). Затем отфильтруйте набор запросов, чтобы получить записи с рангом 1, который соответствует самой поздней записи для каждого месяца.

Попробуйте это:

from django.db.models import Window, F
from django.db.models.functions import DenseRank, ExtractMonth
from django_cte import With


class Model1(models.Model):
    name = models.CharField(max_length=100)
    created = models.DateTimeField(auto_now_add=True)


cte = With(
    Model1.objects.annotate(
        month=ExtractMonth("created"),
        rank=Window(
            expression=DenseRank(),
            partition_by=[ExtractMonth("created")],
            order_by=F("created").desc(),
        ),
    )
)


latest_records = Model1.objects.annotate(
    month=ExtractMonth("created"),
    rank=Window(
        expression=DenseRank(),
        partition_by=[ExtractMonth("created")],
        order_by=F("created").desc(),
    ),
).filter(rank=1)

for record in latest_records:
    print(record.id, record.name, record.created)
Вернуться на верх