514👍
There is no ‘built in’ way to do this. Django will raise the DoesNotExist exception every time.
The idiomatic way to handle this in python is to wrap it in a try catch:
try:
go = SomeModel.objects.get(foo='bar')
except SomeModel.DoesNotExist:
go = None
What I did do, is to subclass models.Manager, create a safe_get
like the code above and use that manager for my models. That way you can write: SomeModel.objects.safe_get(foo='bar')
.
320👍
Since django 1.6 you can use first() method like so:
Content.objects.filter(name="baby").first()
- [Django]-How to implement FirebaseDB with a Django Web Application
- [Django]-Django: Arbitrary number of unnamed urls.py parameters
- [Django]-Passing STATIC_URL to file javascript with django
58👍
You can create a generic function for this.
def get_or_none(classmodel, **kwargs):
try:
return classmodel.objects.get(**kwargs)
except classmodel.DoesNotExist:
return None
Use this like below:
go = get_or_none(Content,name="baby")
go
will be None
if no entry matches else will return the Content entry.
Note:It will raises exception MultipleObjectsReturned
if more than one entry returned for name="baby"
.
You should handle it on the data model to avoid this kind of error but you may prefer to log it at run time like this:
def get_or_none(classmodel, **kwargs):
try:
return classmodel.objects.get(**kwargs)
except classmodel.MultipleObjectsReturned as e:
print('ERR====>', e)
except classmodel.DoesNotExist:
return None
- [Django]-Python Django Gmail SMTP setup
- [Django]-Django template can't see CSS files
- [Django]-Removing 'Sites' from Django admin page
51👍
get()
raises aDoesNotExist
exception if an object is not found for the given parameters. This exception is also an attribute of the model class. TheDoesNotExist
exception inherits fromdjango.core.exceptions.ObjectDoesNotExist
You can catch the exception and assign None
to go.
from django.core.exceptions import ObjectDoesNotExist
try:
go = Content.objects.get(name="baby")
except ObjectDoesNotExist:
go = None
- [Django]-Django FileField upload is not working for me
- [Django]-Django select_for_update cannot be used outside of a transaction
- [Django]-Django model CharField: max_length does not work?
27👍
You can do it this way:
go = Content.objects.filter(name="baby").first()
Now go variable could be either the object you want or None
Ref: https://docs.djangoproject.com/en/1.8/ref/models/querysets/#django.db.models.query.QuerySet.first
- [Django]-Alowing 'fuzzy' translations in django pages?
- [Django]-Django: Safely Remove Old Migrations?
- [Django]-Heroku, postgreSQL, django, comments, tastypie: No operator matches the given name and argument type(s). You might need to add explicit type casts
22👍
To make things easier, here is a snippet of the code I wrote, based on inputs from the wonderful replies here:
class MyManager(models.Manager):
def get_or_none(self, **kwargs):
try:
return self.get(**kwargs)
except ObjectDoesNotExist:
return None
And then in your model:
class MyModel(models.Model):
objects = MyManager()
That’s it.
Now you have MyModel.objects.get() as well as MyModel.objetcs.get_or_none()
- [Django]-Django switching, for a block of code, switch the language so translations are done in one language
- [Django]-Can I access constants in settings.py from templates in Django?
- [Django]-Referencing multiple submit buttons in django
19👍
you could use exists
with a filter:
Content.objects.filter(name="baby").exists()
#returns False or True depending on if there is anything in the QS
just an alternative for if you only want to know if it exists
- [Django]-How to check if ManyToMany field is not empty?
- [Django]-What is a "slug" in Django?
- [Django]-On Heroku, is there danger in a Django syncdb / South migrate after the instance has already restarted with changed model code?
10👍
It’s one of those annoying functions that you might not want to re-implement:
from annoying.functions import get_object_or_None
#...
user = get_object_or_None(Content, name="baby")
- [Django]-Django simple_tag and setting context variables
- [Django]-Django error: got multiple values for keyword argument
- [Django]-How to run a celery worker with Django app scalable by AWS Elastic Beanstalk?
- [Django]-Django Multiple Authentication Backend for one project
- [Django]-Django F() division – How to avoid rounding off
- [Django]-Ignoring Django Migrations in pyproject.toml file for Black formatter
7👍
Handling exceptions at different points in your views could really be cumbersome..What about defining a custom Model Manager, in the models.py file, like
class ContentManager(model.Manager):
def get_nicely(self, **kwargs):
try:
return self.get(kwargs)
except(KeyError, Content.DoesNotExist):
return None
and then including it in the content Model class
class Content(model.Model):
...
objects = ContentManager()
In this way it can be easily dealt in the views i.e.
post = Content.objects.get_nicely(pk = 1)
if post:
# Do something
else:
# This post doesn't exist
- [Django]-DRF: custom ordering on related serializers
- [Django]-Celery : Execute task after a specific time gap
- [Django]-Github issues api 401, why? (django)
5👍
If you want a simple one-line solution that doesn’t involve exception handling, conditional statements or a requirement of Django 1.6+, do this instead:
x = next(iter(SomeModel.objects.filter(foo='bar')), None)
- [Django]-Speeding up Django Testing
- [Django]-Whats the difference between using {{STATIC_URL}} and {% static %}
- [Django]-Django's Double Underscore
5👍
I think it isn’t bad idea to use get_object_or_404()
from django.shortcuts import get_object_or_404
def my_view(request):
my_object = get_object_or_404(MyModel, pk=1)
This example is equivalent to:
from django.http import Http404
def my_view(request):
try:
my_object = MyModel.objects.get(pk=1)
except MyModel.DoesNotExist:
raise Http404("No MyModel matches the given query.")
You can read more about get_object_or_404() in django online documentation.
- [Django]-Suppress "?next=blah" behavior in django's login_required decorator
- [Django]-Why does DEBUG=False setting make my django Static Files Access fail?
- [Django]-Why won't Django use IPython?
3👍
From django 1.7 onwards you can do like:
class MyQuerySet(models.QuerySet):
def get_or_none(self, **kwargs):
try:
return self.get(**kwargs)
except self.model.DoesNotExist:
return None
class MyBaseModel(models.Model):
objects = MyQuerySet.as_manager()
class MyModel(MyBaseModel):
...
class AnotherMyModel(MyBaseModel):
...
The advantage of “MyQuerySet.as_manager()” is that both of the following will work:
MyModel.objects.filter(...).get_or_none()
MyModel.objects.get_or_none()
- [Django]-How to change empty_label for modelForm choice field?
- [Django]-Django: Multiple forms possible when using FormView?
- [Django]-Django – getting Error "Reverse for 'detail' with no arguments not found. 1 pattern(s) tried:" when using {% url "music:fav" %}
2👍
This is a copycat from Django’s get_object_or_404 except that the method returns None. This is extremely useful when we have to use only()
query to retreive certain fields only. This method can accept a model or a queryset.
from django.shortcuts import _get_queryset
def get_object_or_none(klass, *args, **kwargs):
"""
Use get() to return an object, or return None if object
does not exist.
klass may be a Model, Manager, or QuerySet object. All other passed
arguments and keyword arguments are used in the get() query.
Like with QuerySet.get(), MultipleObjectsReturned is raised if more than
one object is found.
"""
queryset = _get_queryset(klass)
if not hasattr(queryset, 'get'):
klass__name = klass.__name__ if isinstance(klass, type) else klass.__class__.__name__
raise ValueError(
"First argument to get_object_or_none() must be a Model, Manager, "
"or QuerySet, not '%s'." % klass__name
)
try:
return queryset.get(*args, **kwargs)
except queryset.model.DoesNotExist:
return None
- [Django]-Are sessions needed for python-social-auth
- [Django]-Django models: Only permit one entry in a model?
- [Django]-What is the difference render() and redirect() in Django?
2👍
I use Django 2.2.16. And this is how I solve this problem:
from typing import Any
from django.core.exceptions import ObjectDoesNotExist
from django.db import models
from django.db.models.base import ModelBase
from django.db.models.manager import Manager
class SManager(Manager):
def get_if_exist(self, *args: Any, **kwargs: Any):
try:
return self.get(*args, **kwargs)
except ObjectDoesNotExist:
return None
class SModelBase(ModelBase):
def _prepare(cls):
manager = SManager()
manager.auto_created = True
cls.add_to_class("objects", manager)
super()._prepare()
class Meta:
abstract = True
class SModel(models.Model, metaclass=SModelBase):
managers = False
class Meta:
abstract = True
And after that, in every models, you just need to import in:
from custom.models import SModel
class SUser(SModel):
pass
And in views
, you can call like this:
SUser.objects.get_if_exist(id=1)
- [Django]-How can I get tox and poetry to work together to support testing multiple versions of a Python dependency?
- [Django]-Suppress "?next=blah" behavior in django's login_required decorator
- [Django]-Django middleware difference between process_request and process_view
1👍
Here’s a variation on the helper function that allows you to optionally pass in a QuerySet
instance, in case you want to get the unique object (if present) from a queryset other than the model’s all
objects queryset (e.g. from a subset of child items belonging to a parent instance):
def get_unique_or_none(model, queryset=None, **kwargs):
"""
Performs the query on the specified `queryset`
(defaulting to the `all` queryset of the `model`'s default manager)
and returns the unique object matching the given
keyword arguments. Returns `None` if no match is found.
Throws a `model.MultipleObjectsReturned` exception
if more than one match is found.
"""
if queryset is None:
queryset = model.objects.all()
try:
return queryset.get(**kwargs)
except model.DoesNotExist:
return None
This can be used in two ways, e.g.:
obj = get_unique_or_none(Model, **kwargs)
as previosuly discussedobj = get_unique_or_none(Model, parent.children, **kwargs)
- [Django]-DRF: custom ordering on related serializers
- [Django]-Missing Table When Running Django Unittest with Sqlite3
- [Django]-Suddenly when running tests I get "TypeError: 'NoneType' object is not iterable
1👍
Without exception:
if SomeModel.objects.filter(foo='bar').exists():
x = SomeModel.objects.get(foo='bar')
else:
x = None
Using an exception:
try:
x = SomeModel.objects.get(foo='bar')
except SomeModel.DoesNotExist:
x = None
There is a bit of an argument about when one should use an exception in python. On the one hand, “it is easier to ask for forgiveness than for permission”. While I agree with this, I believe that an exception should remain, well, the exception, and the “ideal case” should run without hitting one.
- [Django]-Determine variable type within django template
- [Django]-Using the reserved word "class" as field name in Django and Django REST Framework
- [Django]-Django – How to use decorator in class-based view methods?
1👍
We can use Django builtin exception which attached to the models named as .DoesNotExist
. So, we don’t have to import ObjectDoesNotExist
exception.
Instead doing:
from django.core.exceptions import ObjectDoesNotExist
try:
content = Content.objects.get(name="baby")
except ObjectDoesNotExist:
content = None
We can do this:
try:
content = Content.objects.get(name="baby")
except Content.DoesNotExist:
content = None
- [Django]-Malformed Packet: Django admin nested form can't submit, connection was reset
- [Django]-How do I deploy Django on AWS?
- [Django]-Name '_' is not defined
1👍
I was facing with the same problem too. It’s hard to write and read try-except
for each time when you want to get an element from your model as in @Arthur Debert’s answer. So, my solution is to create an Getter
class which is inherited by the models:
class Getter:
@classmethod
def try_to_get(cls, *args, **kwargs):
try:
return cls.objects.get(**kwargs)
except Exception as e:
return None
class MyActualModel(models.Model, Getter):
pk_id = models.AutoField(primary_key=True)
...
In this way, I can get the actual element of MyActualModel
or None
:
MyActualModel.try_to_get(pk_id=1)
- [Django]-How to format time in django-rest-framework's serializer?
- [Django]-How do you use the django-filter package with a list of parameters?
- [Django]-Get count of related model efficiently in Django
1👍
Simple way:
if query.exists():
do something….
or
if query.exists() is False:
do something…
- [Django]-How do I match the question mark character in a Django URL?
- [Django]-Why am I getting this error in Django?
- [Django]-Django Cannot set values on a ManyToManyField which specifies an intermediary model. Use Manager instead
0👍
I prefer this method without using exceptions. It also handles multiple objects as well as no objects.
go_list = Content.objects.filter(name="baby")
if (len(go_list) == 1):
go = go_list[0]
else:
go = None # optionally do other things if there are multiple objects / no objects.
- [Django]-Django annotation with nested filter
- [Django]-Django – Rotating File Handler stuck when file is equal to maxBytes
- [Django]-How to get getting base_url in django template
- [Django]-CORS error while consuming calling REST API with React
- [Django]-405 "Method POST is not allowed" in Django REST framework
- [Django]-How to upload a file in Django?
0👍
As it has been mentioned in other answers, you can use
filter(**kwargs).first()
The issue with this method is it never throws a MultipleObjectsReturned error if the query returns multiple objects. This may not always be desirable. Assume you have the following database table
id | first_name | last_name |
---|---|---|
1 | Keenen | Wayans |
2 | Marlon | Wayans |
3 | Shawn | Wayans |
Person.objects.filter(last_name="Wayans").first()
will always return Keenen Wayans. The user will never know there are other ‘Wayans’
If you don’t like this, below is my reimplementation of Django’s shortcut method get_object_or_404. If no object is found, it returns None
, but if the query returns multiple objects, it throws a MultipleObjectsReturned exception. I would rather handle MultipleObjectsReturned exception, instead of returning a bogus value to the user.
In a separate file called shortcuts.py
, create a method called get_object_or_none.
def get_object_or_none(klass, *args, **kwargs):
"""
Use get() to return an object, or returns None if the object
does not exist instead of throwing an exception.
klass may be a Model, Manager, or QuerySet object. All other passed
arguments and keyword arguments are used in the get() query.
Like with QuerySet.get(), MultipleObjectsReturned is raised if more than
one object is found.
"""
queryset = klass._default_manager.all() if hasattr(klass, "_default_manager") else klass
if not hasattr(queryset, "get"):
klass__name = (
klass.__name__ if isinstance(klass, type) else klass.__class__.__name__
)
raise ValueError(
"First argument to get_object_or_none() must be a Model, Manager, "
"or QuerySet, not '%s'." % klass__name
)
try:
return queryset.get(*args, **kwargs)
except queryset.model.DoesNotExist:
return None
Then in views.py
from myapp.shortcuts import get_object_or_none
person = get_object_or_none(Person, first_name='Shawn', last_name='Wayans')
#person is 'Shawn Wayans'
person = get_object_or_none(Person, last_name='Hendrix')
#person is None as database has no person with last name 'Hendrix'
person = get_object_or_none(Person, last_name='Wayans')
#throws 'MultipleObjectsReturned' error since multiple persons returned.
- [Django]-Django REST Framework – 405 METHOD NOT ALLOWED using SimpleRouter
- [Django]-Django create userprofile if does not exist
- [Django]-Django CMS fails to synch db or migrate
-2👍
How about a slice? It will parse to a limit 1.
go = Content.objects.filter(name="baby")[0]
- [Django]-Django get objects not referenced by foreign key
- [Django]-Django Sitemaps and "normal" views
- [Django]-ImportError: Failed to import test module: