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.
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
- [Django]-Django delete FileField
- [Django]-Prevent django admin from escaping html
- [Django]-Show page items count in django pagination
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.
- [Django]-Load a Django template tag library for all views by default
- [Django]-Django queries: how to filter objects to exclude id which is in a list?
- [Django]-Best way to make Django's login_required the default
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)
.
- [Django]-Django: Country drop down list?
- [Django]-"Fixed default value provided" after upgrading to Django 1.8
- [Django]-Django return HttpResponseRedirect to an url with a parameter