Получить последнюю запись об объекте

У меня есть две модели: Cat (id, name) CatRecords (id, cat_id, status, created_time)

Каждый день у кошки есть одна запись о состоянии кошки

Я хочу получить все кошки и последнюю запись каждой из них, отсортированную по времени создания_записи. Я могу получить все записи о каждой кошке, но не могу получить последнюю запись о каждой

Класс запроса Cat:

class Query(graphene.ObjectType):
    all_cats = graphene.List(CatType)
    cat = graphene.Field(CatType, cat_id=graphene.UUID())
    latest_record = graphene.Field(CatRecordType)

    def resolve_all_cats(self, info, **kwargs):
        cats = Cat.objects.all()
        return cats

    def resolve_cat(self, info, cat_id):
        return Cat.objects.get(cat_id=cat_id)

    def resolve_latest_record(self, info):
        subquery = CatRecord.objects.filter(cat_id=OuterRef("id")).order_by(
            "-created_time"
        )
        return (
            Cat.objects.all()
            .annotate(latest_record=Subquery(subquery.values("id")[:1]))
            .values("latest_record")
        )

Мой запрос

query {
  latestRecord{
    id
    name
  }
}

ошибка

{
  "errors": [
    {
      "message": "Received incompatible instance \"<QuerySet [{'latest_record': UUID('3d2af716-94aa-4952-9050-4d7f69384e3d')}, {'latest_record': UUID('0705aeda-a2ec-47c3-8bd1-1aa445c40444')}]>\".",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "latestRecord"
      ]
    }
  ],
  "data": {
    "latestRecord": null
  }
}

Мы можем работать с FilteredRelation [Django-doc] здесь:

Cat.objects.annotate(
    latest_record=FilteredRelation(
        'catrecords_set',
        condition=Q(
            pk=Subquery(
                CatRecords.objects.filter(cat_id=OuterRef('pk'))
                .order_by('-created_time')
                .values('pk')[:1]
            ),
        ),
    ),
).select_related('latest_record')

Таким образом, для каждого Cat будет получена последняя CatRecords и добавлена как .latest_record, или None в противном случае.


Note: Normally a Django model is given a singular name [django-antipatterns], so CatRecord instead of CatRecords.

Вернуться на верх