【发布时间】:2020-06-15 09:46:12
【问题描述】:
我正在尝试通过 Django ORM 返回一个导致该对象的查询:
[
...,
{
"id": 1,
"product_id": 1,
"created_at": "2020-03-03T03:34:59.275941Z",
"updated_at": "2020-03-03T03:34:59.291653Z",
"latest_comment": {
"comment": "Leaving a comment",
"author": {
"id": 1,
"name": "John Lennon",
"profile": {
"avatar": null
}
},
"updated_at": "2020-03-03T03:34:59.329229Z"
}
}
]
我有以下型号:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
avatar = models.ImageField(upload_to="avatar", blank=True)
created_at = models.DateTimeField(default=timezone.now)
updated_at = AutoDateTimeField(default=timezone.now)
class Product(models.Model):
name = models.CharField(max_length=100)
created_at = models.DateTimeField(default=timezone.now)
updated_at = AutoDateTimeField(default=timezone.now)
class Note(models.Model):
product = models.ForeignKey(Product, related_name="notes", on_delete=models.CASCADE)
created_at = models.DateTimeField(default=timezone.now)
updated_at = AutoDateTimeField(default=timezone.now)
class Comment(models.Model):
note = models.ForeignKey(Note, related_name="comments", on_delete=models.CASCADE)
comment = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(default=timezone.now)
updated_at = AutoDateTimeField(default=timezone.now)
class Meta:
get_latest_by = "updated_at"
我已经能够用下面的代码实现上面的结构,但是它引入了N + 1问题。
product = Product.objects.get(id=1)
notes = []
for note in product.notes.all():
try:
note.latest_comment = note.comments.latest()
except ObjectDoesNotExist:
note.latest_comment = None
notes.append(note)
我一直在玩prefetch_related 以及Max 函数的注释,但没有取得多大成功。我还能够编写一个原始查询,可以使用一些 Postgres 和 json_build_object 函数来重现这一点。我试图让 ORM 工作的原因是我想使用CursorPagination,而使用.raw() 或RawSql() 似乎与CursorPagination 不兼容。
【问题讨论】:
标签: django django-rest-framework django-orm