Django matching query does not exist (tested)
Post matching query does not exist is Post.DoesNotExist, raised when .get() finds no row; get() returned more than one is MultipleObjectsReturned. Catch the model's exception, use .first(), or get_object_or_404 in views.
Setup
One model, an in-memory SQLite table, and three rows: one hello and two dup. common.py:
import sys; sys.path.insert(0, '/w/proj')
import django
from django.conf import settings
settings.configure(INSTALLED_APPS=['blog'],
DATABASES={'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:'}})
django.setup()
from django.db import connection
from blog.models import Post
with connection.schema_editor() as ed:
ed.create_model(Post)
Post.objects.create(title='hello'); Post.objects.create(title='dup'); Post.objects.create(title='dup')
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=100)
1. Reproduce both errors
from common import *
from django.core.exceptions import ObjectDoesNotExist
for kw in [{'pk': 99}, {'title': 'dup'}]:
try:
Post.objects.get(**kw)
except Exception as e:
print(kw, '->', type(e).__qualname__ + ':', e)
print(' ObjectDoesNotExist subclass:', isinstance(e, ObjectDoesNotExist))
Output:
{'pk': 99} -> Post.DoesNotExist: Post matching query does not exist.
ObjectDoesNotExist subclass: True
{'title': 'dup'} -> Post.MultipleObjectsReturned: get() returned more than one Post -- it returned 2!
ObjectDoesNotExist subclass: False
.get() expects exactly one row. Zero rows raises <Model>.DoesNotExist ("matching query does not exist"); two or more raises <Model>.MultipleObjectsReturned with the count. Each model has its own subclasses; DoesNotExist also inherits from django.core.exceptions.ObjectDoesNotExist, which is handy for catching the error for any model.
2. Fixes: catch it, or use first()
from common import *
# 1. catch the model-specific exception
try:
p = Post.objects.get(pk=99)
except Post.DoesNotExist:
p = None
print('caught:', p)
# 2. first() returns None instead of raising (and never raises MultipleObjectsReturned)
print('first():', Post.objects.filter(pk=99).first(), Post.objects.filter(title='dup').first().pk)
# 3. get_or_create on a non-unique field still raises when duplicates exist
try:
Post.objects.get_or_create(title='dup')
except Post.MultipleObjectsReturned as e:
print('get_or_create:', type(e).__qualname__ + ':', e)
Output:
caught: None
first(): None 2
get_or_create: Post.MultipleObjectsReturned: get() returned more than one Post -- it returned 2!
- Catch
Post.DoesNotExist(not a bareexcept) when a missing row is expected. .filter(...).first()returnsNonefor no rows and the lowest-pk row when there are several; it never raises either error. Only use it when "any one of them" is really fine.get_or_create()does aget()first, so it raisesMultipleObjectsReturnedif duplicates already exist. The lasting fix for duplicates is aunique=Truefield or aUniqueConstraint, after cleaning the existing rows.
3. In views: get_object_or_404
from common import *
from django.http import Http404
from django.shortcuts import get_object_or_404
for kw in [{'pk': 99}, {'title': 'dup'}]:
try:
get_object_or_404(Post, **kw)
except Exception as e:
print(kw, '->', type(e).__qualname__ + ':', e)
Output:
{'pk': 99} -> Http404: No Post matches the given query.
{'title': 'dup'} -> Post.MultipleObjectsReturned: get() returned more than one Post -- it returned 2!
get_object_or_404 converts DoesNotExist into Http404 (a 404 page, not a 500), but MultipleObjectsReturned passes through unchanged and becomes a 500 error. Look up by pk or a unique field in views.
Related: Django NoReverseMatch, Django settings are not configured, SQLAlchemy IntegrityError UNIQUE constraint failed.
Frequently asked questions
How do I avoid 'matching query does not exist' in Django?
Catch Model.DoesNotExist, use .filter(...).first() which returns None, or get_object_or_404 in views.
Does get_object_or_404 handle MultipleObjectsReturned?
No. In Django 6.1.2 only DoesNotExist becomes Http404; MultipleObjectsReturned propagates as a 500.
Why does get_or_create raise MultipleObjectsReturned?
It calls get() first, so existing duplicate rows make it raise. Add a unique constraint after removing duplicates.
Written with AI assistance. Measured on 2026-10-23 with Django 6.1.2 and Python 3.14.7 (python:3-alpine in Docker, SQLite in memory). Each block was run verbatim and the output pasted unedited. PlainHeaders is our extension; Python and Django are free.