[Django]-How to exclude results with get_object_or_404?

23đź‘Ť

âś…

Use django.db.models.Q:

from django.db.models import Q

model = get_object_or_404(MyModel, ~Q(status='deleted'), pk=id)

The Q objects lets you do NOT (with ~ operator) and OR (with | operator) in addition to AND.

Note that the Q object must come before pk=id, because keyword arguments must come last in Python.

👤interjay

15đź‘Ť

The most common use case is to pass a Model. However, you can also pass a QuerySet instance:

queryset = Model.objects.exclude(status='deleted')
get_object_or_404(queryset, pk=1)

Django docs example:
https://docs.djangoproject.com/en/1.10/topics/http/shortcuts/#id2

👤Jamneck

1đź‘Ť

There’s another way instead of using Q objects. Instead of passing the model to get_object_or_404 just pass the QuerySet to the function instead:

model = get_object_or_404(MyModel.objects.filter(pk=id).exclude(status='deleted'))

One side effect of this, however, is that it will raise a MultipleObjectsReturned exception if the QuerySet returns multiple results.

👤Corey McMahon

0đź‘Ť

get_object_or_404 utilizes the get_queryset method of the object manager. If you override the get_queryset method to only return items that aren’t “deleted” then get_object_or_404 will automatically behave as you want. However, overriding get_queryset like this will likely have issues elsewhere (perhaps in the admin pages), but you could add an alternate manager for when you need to access the soft deleted items.

from django.db import models

class ModelManger(models.Manger):
    def get_queryset(self):
        return super(ModelManger, self).get_queryset().exclude(status='deleted')

class Model(models.Model):
    # ... model properties here ...

    objects = ModelManager()
    all_objects = models.Manager()

So if you need only non-deleted items you can do get_object_or_404(Models, id=id) but if you need all items you can do get_object_or_404(Models.all_objects, id=id).

👤Tim Tisdall

Leave a comment