Count not figure out a good title for the question.
I have the following model where each host’s current list of packages are saved. Say there are three hosts, hostA
, hostB
and hostC
and we are updating the latest packages from the hosts a few times daily via HostDetails
.
Now, for a package libc-bin
with version 0.1.0
was there till yesterday and today both hostB
and hostC
got updated to libc-bin
with version 0.2.0
. Today’s latest entry for hostA
still has libc-bin
with version 0.1.0
.
class Host(models.Model):
hostname = models.CharField(max_length=200)
class Package(models.Model):
name = models.CharField(max_length=255)
version = models.CharField(max_length=255)
class Meta:
unique_together = ("name", "version")
class HostDetails(models.Model):
time = models.DateTimeField()
host = models.ForeignKey(Host, on_delete=models.CASCADE)
packages = models.ManyToManyField(Package)
I want to query all the hosts which still have libc-bin
version 0.1.0
(answer hostA
). How can I do this?
Hi Kushaldas,
I’m not the best at this, and there are other guys on here that are like Django masters, so my answer is probably not best way, but ill give it a go.
I think you are asking to return any host
in HostDetails
where the Package
Name
and Version
are libc-bin
and 0.1.0
version_check = HostDetails.objects.filter(
packages__name = 'libc-bin',
packages__version='0.1.0'
).order_by('-time')
for item in version_check:
print(item.host.hostname)
print(item.time)
print(item.packages.all())
I am trying to ask for the hosts where in the latest hostdetails (for that host) name
is libc-bin
and version is 0.1.0
.
Ok, understood.
I think this gets what you need. There is probably a much simpler way.
latest_host_details_subquery = HostDetails.objects.filter(
host=OuterRef('pk')
).order_by('-time').values('pk')[:1]
hosts_with_package = Host.objects.filter(
hostdetails__pk__in=Subquery(latest_host_details_subquery),
hostdetails__packages__name='libc-bin',
hostdetails__packages__version='0.1.0'
).distinct()
2 Likes
YES!!, can you please explain me a bit more? I guess I will have to read through Subquery, never used that before.
If it were me, it would be like this.
a = HostDetails.objects.filter(packeages__name='libc-bin').values_list('host_id', flat=True)
b = Host.objects.filter(pk__in=a)
c = HostDetails.objects.fiter(host_id=OuterRef('pk')).order_by('-time')
d = b.annotate(
version=Subquery(c.values('packages__version')),
time=Subquery(c.values('time'))
).filter(version='0.1.0')
for i in d: print(i.__dict__)