menu

Questions & Answers

Filter queryset for many-to-many field for any foreign item matching specific criteria

I have 2 models:

class BackupItems(models.Model):
    name = models.CharField(max_length=100)

class CloudObjects(models.Model):
    creation_time = models.DateTimeField()
    removed_date = models.DateTimeField()
    item = models.ManyToManyField(BackupItems, db_table='cloud_object_items')

This is holding data for some backup operations. CloudObject is a table with information when item was created and when it was deleted. For legacy issues, removed date is hardcoded as 2099-12-31 for all new entries. Once it's deleted, this date is substitute with real date.

In the views I have simply query, where I list all items from BackupItems.

BackupItems.objects.all()

Now, I'd like to list only those BackupItems which have any CloudObjects in the future ( removed_date = 2099-21-31). I dont care what is that given item, if this CloudObject for given BackupItem exists in the future, it's fine for me. I don't want to see any item in queryset, where there are no CloudObjects in future for given BackupItem.

How to crate this kind of view?

Answers(1) :

You could do this by the use of Django ORM's filter() method and passing it to the view as a context variable like so:

from django.shortcuts import render
from .models import BackupItems, CloudObjects
import datetime


def backup_items(request):
    future_date = datetime.datetime(2099, 12, 31)
    backup_items = BackupItems.objects.filter(cloudobject__removed_date=future_date).distinct()
    context = {'backup_items': backup_items}
    return render(request, 'backup_items.html', context)

This will return a queryset of BackupItems objects that have a CloudObject with a removed_date of 2099-12-31. The distinct() method ensures that each BackupItem is returned only once.