Django get latest release QuerySet
class Release(models.Model):
version = models.PositiveIntegerField(default=1)
class Project(models.Model):
project = models.ForeignKey('projects.Project', related_name='releases', on_delete=models.SET_NULL, blank=1, null=1)
def getObjects():
releases = []
for project in Project.objects.all():
if project.releases.all():
releases.append(project.releases.all().order_by('-version')[0])
return releases
можно ли получить кверисет последних релизов каждого проекта, если у него есть релиз? Извините, я буквально не представляю, как написать кверисет.
Есть способ сделать это в одном запросе, вам нужно объединить annotate
и filter
вместе.
Метод заключается в аннотировании каждого объекта с наивысшей версией для каждого проекта, связанного с релизом. Поэтому мы используем двойную аннотацию через отношение project__releases__version
. Это позволяет получить проект, связанный с каждым релизом, получить все связанные с этим проектом релизы и, таким образом, все версии.
Мы можем применить Max
к этому полю, чтобы получить наибольшее значение. Узнав последнюю версию, мы можем просто отфильтровать набор запросов для этого значения с помощью объекта F()
, который получает значение поля.
from django.db.models import Max, F
Release.objects.annotate(
latest_for_project=Max(project__releases__version)
).filter(
latest_for_project=F('release')
)
Вы должны правильно установить связь. Не следует соединять Project
с Project
, если вы хотите иметь связь с Release
:)
Гораздо лучше использовать прямые отношения или метод модели. Тогда вы сможете легче использовать его в любом другом месте вне системы.
class Release(models.Model):
version = models.PositiveIntegerField(default=1)
project = models.ForeignKey('projects.Project', related_name='releases', on_delete=models.SET_NULL, blank=1, null=1)
class Project(models.Model):
# project fields
def latest_release(self):
return self.releases.order_by('-version').first()
Затем в фукции (или оболочке):
def get_latest_releases():
releases = []
for project in Project.objects.all():
if project.latest_release():
releases.append(project.latest_release())
return releases