Django - 查询:使用相关模型字段注释查询集
Django - Query : Annotate Queryset with Related Model fields
我在 Django 中使用 PostgreSQL 遵循模式。
Class Person (models.Model):
name = models.CharField(max_length=255)
email= models.CharField(max_legth = 255)
created_at = models.DateTimeField()
Class PersonTask(models.Model):
person = models.ForeignKey(Person)
title = models.TextField()
created_at = models.DateTimeField()
Class PersonHistory(models.Model):
person = models.ForeignKey(Person)
note = models.TextField()
created_at = models.DateTimeField()
现在我需要像查询 Person 的所有值一样查询数据库,最新的 PersonTask__title
为 max_task
,最新的 PersonHistory__note
为 max_note
例如:
<Queryset: [
{name: "abc" ,email:"abc@gmail.com",created_at :"2019-01-02", max_task:"This is my latest tasktitle" , max_note: "This is my latest history note"},
{name: "abcd" ,email:"abcd@gmail.com",created_at :"2019-03-02", max_task:"This is my latest tasktitle for abcd" , max_note: "This is my latest history note for abcd"}
]>
但是,我最多可以通过
获取最新任务和最新历史的id
Person.objects.filter(customer_id= 1).\
annotate( max_task = Max('persontask')).\
annotate(max_note = Max('personhistory')).\
order_by('-id')
或者使用以下查询的随机任务或注释文本
Person.objects.filter(customer_id= 1).\
annotate( max_task = Max('persontask__title')).\
annotate(max_note = Max('personhistory__note')).\
order_by('-id')
如何解决这个问题??
如果任务和历史记录与人相关,您需要模型之间的关系。
像这样。
class PersonTask(models.Model):
person = models.ForeignKey(Person, related_name="tasks", on_delete=models.CASCADE)
title = models.TextField()
created_at = models.DateTimeField()
class PersonHistory(models.Model):
person = models.ForeignKey(Person, related_name="histories", on_delete=models.CASCADE)
note = models.TextField()
created_at = models.DateTimeField()
然后您可以获得上一个任务和上一个历史记录:
person = Person.objects.get(name="name")
person.tasks.last()
person.histories.last()
由于你没有提到这些模型之间的外键,我怀疑 Task 和 History 在名为 person 的字段中与 Person 有 FK。
我会结合使用子查询和 OuterRef 来处理这个查询
from django.db.models import OuterRef, Subquery
result = (
Person.objects
.filter(customer_id=1)
.annotate(
task_title=Subquery(Task.objects.filter(person=OuterRef('pk')).order_by('-created_at').values('title')[:1]),
history_note=Subquery(HistoryNote.objects.filter(person=OuterRef('pk')).order_by('-created_at').values('note')[:1])
)
.order_by('-id')
)
我在 Django 中使用 PostgreSQL 遵循模式。
Class Person (models.Model):
name = models.CharField(max_length=255)
email= models.CharField(max_legth = 255)
created_at = models.DateTimeField()
Class PersonTask(models.Model):
person = models.ForeignKey(Person)
title = models.TextField()
created_at = models.DateTimeField()
Class PersonHistory(models.Model):
person = models.ForeignKey(Person)
note = models.TextField()
created_at = models.DateTimeField()
现在我需要像查询 Person 的所有值一样查询数据库,最新的 PersonTask__title
为 max_task
,最新的 PersonHistory__note
为 max_note
例如:
<Queryset: [
{name: "abc" ,email:"abc@gmail.com",created_at :"2019-01-02", max_task:"This is my latest tasktitle" , max_note: "This is my latest history note"},
{name: "abcd" ,email:"abcd@gmail.com",created_at :"2019-03-02", max_task:"This is my latest tasktitle for abcd" , max_note: "This is my latest history note for abcd"}
]>
但是,我最多可以通过
获取最新任务和最新历史的idPerson.objects.filter(customer_id= 1).\
annotate( max_task = Max('persontask')).\
annotate(max_note = Max('personhistory')).\
order_by('-id')
或者使用以下查询的随机任务或注释文本
Person.objects.filter(customer_id= 1).\
annotate( max_task = Max('persontask__title')).\
annotate(max_note = Max('personhistory__note')).\
order_by('-id')
如何解决这个问题??
如果任务和历史记录与人相关,您需要模型之间的关系。 像这样。
class PersonTask(models.Model):
person = models.ForeignKey(Person, related_name="tasks", on_delete=models.CASCADE)
title = models.TextField()
created_at = models.DateTimeField()
class PersonHistory(models.Model):
person = models.ForeignKey(Person, related_name="histories", on_delete=models.CASCADE)
note = models.TextField()
created_at = models.DateTimeField()
然后您可以获得上一个任务和上一个历史记录:
person = Person.objects.get(name="name")
person.tasks.last()
person.histories.last()
由于你没有提到这些模型之间的外键,我怀疑 Task 和 History 在名为 person 的字段中与 Person 有 FK。
我会结合使用子查询和 OuterRef 来处理这个查询
from django.db.models import OuterRef, Subquery
result = (
Person.objects
.filter(customer_id=1)
.annotate(
task_title=Subquery(Task.objects.filter(person=OuterRef('pk')).order_by('-created_at').values('title')[:1]),
history_note=Subquery(HistoryNote.objects.filter(person=OuterRef('pk')).order_by('-created_at').values('note')[:1])
)
.order_by('-id')
)