210👍
get()
is provided specifically for this case. Use it.
Option 2 is almost precisely how the get()
method is actually implemented in Django, so there should be no “performance” difference (and the fact that you’re thinking about it indicates you’re violating one of the cardinal rules of programming, namely trying to optimize code before it’s even been written and profiled — until you have the code and can run it, you don’t know how it will perform, and trying to optimize before then is a path of pain).
31👍
You can install a module called django-annoying and then do this:
from annoying.functions import get_object_or_None
obj = get_object_or_None(MyModel, id=1)
if not obj:
#omg the object was not found do some error stuff
- [Django]-Django – getting Error "Reverse for 'detail' with no arguments not found. 1 pattern(s) tried:" when using {% url "music:fav" %}
- [Django]-How to change User representation in Django Admin when used as Foreign Key?
- [Django]-How to pass django rest framework response to html?
20👍
1 is correct. In Python an exception has equal overhead to a return. For a simplified proof you can look at this.
2 This is what Django is doing in the backend. get
calls filter
and raises an exception if no item is found or if more than one object is found.
- [Django]-Do I need Nginx with Gunicorn if I am not serving any static content?
- [Django]-Django project models.py versus app models.py
- [Django]-How to resize the new uploaded images using PIL before saving?
18👍
I’m a bit late to the party, but with Django 1.6 there is the first()
method on querysets.
https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.first
Returns the first object matched by the queryset, or None if there is no matching object. If the QuerySet has no ordering defined, then the queryset is automatically ordered by the primary key.
Example:
p = Article.objects.order_by('title', 'pub_date').first()
Note that first() is a convenience method, the following code sample is equivalent to the above example:
try:
p = Article.objects.order_by('title', 'pub_date')[0]
except IndexError:
p = None
- [Django]-Django: show the count of related objects in admin list_display
- [Django]-Django models avoid duplicates
- [Django]-Django custom management commands: AttributeError: 'module' object has no attribute 'Command'
11👍
Why do all that work? Replace 4 lines with 1 builtin shortcut. (This does its own try/except.)
from django.shortcuts import get_object_or_404
obj = get_object_or_404(MyModel, id=1)
- [Django]-What is a "slug" in Django?
- [Django]-How can I temporarily disable a foreign key constraint in MySQL?
- [Django]-Factory-boy create a list of SubFactory for a Factory
8👍
I can’t speak with any experience of Django but option #1 clearly tells the system that you are asking for 1 object, whereas the second option does not. This means that option #1 could more easily take advantage of cache or database indexes, especially where the attribute you’re filtering on is not guaranteed to be unique.
Also (again, speculating) the second option may have to create some sort of results collection or iterator object since the filter() call could normally return many rows. You’d bypass this with get().
Finally, the first option is both shorter and omits the extra temporary variable – only a minor difference but every little helps.
- [Django]-How do you log server errors on django sites
- [Django]-How to get the name of current app within a template?
- [Django]-UUID as default value in Django model
7👍
Some more info about exceptions. If they are not raised, they cost almost nothing. Thus if you know you are probably going to have a result, use the exception, since using a conditional expression you pay the cost of checking every time, no matter what. On the other hand, they cost a bit more than a conditional expression when they are raised, so if you expect not to have a result with some frequency (say, 30% of the time, if memory serves), the conditional check turns out to be a bit cheaper.
But this is Django’s ORM, and probably the round-trip to the database, or even a cached result, is likely to dominate the performance characteristics, so favor readability, in this case, since you expect exactly one result, use get()
.
- [Django]-Django return file over HttpResponse – file is not served correctly
- [Django]-Allowing RabbitMQ-Server Connections
- [Django]-How to pull a random record using Django's ORM?
5👍
I’ve played with this problem a bit and discovered that the option 2 executes two SQL queries, which for such a simple task is excessive. See my annotation:
objs = MyModel.objects.filter(id=1) # This does not execute any SQL
if len(objs) == 1: # This executes SELECT COUNT(*) FROM XXX WHERE filter
obj = objs[0] # This executes SELECT x, y, z, .. FROM XXX WHERE filter
else:
# we have no object! do something
pass
An equivalent version that executes a single query is:
items = [item for item in MyModel.objects.filter(id=1)] # executes SELECT x, y, z FROM XXX WHERE filter
count = len(items) # Does not execute any query, items is a standard list.
if count == 0:
return None
return items[0]
By switching to this approach, I was able to substantially reduce number of queries my application executes.
- [Django]-Nginx doesn't serve static
- [Django]-In a Django form, how do I make a field readonly (or disabled) so that it cannot be edited?
- [Django]-Django character set with MySQL weirdness
3👍
.get()
Returns the object matching the given lookup parameters, which should
be in the format described in Field lookups.get() raises MultipleObjectsReturned if more than one object was
found. The MultipleObjectsReturned exception is an attribute of the
model class.get() raises a DoesNotExist exception if an object wasn’t found for
the given parameters. This exception is also an attribute of the model
class.
.filter()
Returns a new QuerySet containing objects that match the given lookup
parameters.
Note
use get() when you want to get a single unique object, and filter()
when you want to get all objects that match your lookup parameters.
- [Django]-How to access request body when using Django Rest Framework and avoid getting RawPostDataException
- [Django]-What is more efficient .objects.filter().exists() or get() wrapped on a try
- [Django]-Do django db_index migrations run concurrently?
1👍
Interesting question, but for me option #2 reeks of premature optimisation. I’m not sure which is more performant, but option #1 certainly looks and feels more pythonic to me.
- [Django]-Serializer call is showing an TypeError: Object of type 'ListSerializer' is not JSON serializable?
- [Django]-Django render_to_string missing information
- [Django]-Django's Double Underscore
1👍
I suggest a different design.
If you want to perform a function on a possible result, you could derive from QuerySet, like this: http://djangosnippets.org/snippets/734/
The result is pretty awesome, you could for example:
MyModel.objects.filter(id=1).yourFunction()
Here, filter returns either an empty queryset or a queryset with a single item. Your custom queryset functions are also chainable and reusable. If you want to perform it for all your entries: MyModel.objects.all().yourFunction()
.
They are also ideal to be used as actions in the admin interface:
def yourAction(self, request, queryset):
queryset.yourFunction()
- [Django]-Error when using django.template
- [Django]-How to run own daemon processes with Django?
- [Django]-Django Model() vs Model.objects.create()
0👍
Option 1 is more elegant, but be sure to use try..except.
From my own experience I can tell you that sometimes you’re sure there cannot possibly be more than one matching object in the database, and yet there will be two… (except of course when getting the object by its primary key).
- [Django]-Suppress "?next=blah" behavior in django's login_required decorator
- [Django]-Uwsgi installation error in windows 7
- [Django]-Where can I find the error logs of nginx, using FastCGI and Django?
0👍
Sorry to add one more take on this issue, but I am using the django paginator, and in my data admin app, the user is allowed to pick what to query on. Sometimes that is the id of a document, but otherwise it is a general query returning more than one object, i.e., a Queryset.
If the user queries the id, I can run:
Record.objects.get(pk=id)
which throws an error in django’s paginator, because it is a Record and not a Queryset of Records.
I need to run:
Record.objects.filter(pk=id)
Which returns a Queryset with one item in it. Then the paginator works just fine.
- [Django]-Django Rest Framework model serializer with out unique together validation
- [Django]-Django.contrib.gis.db.backends.postgis vs django.db.backends.postgresql_psycopg2
- [Django]-UUID as default value in Django model
0👍
get() returns one object as shown below:
{
"name": "John",
"age": "26",
"gender": "Male"
}
filter() returns a QuerySet which has one or more objects as shown below:
[
{
"name": "John",
"age": "26",
"gender": "Male"
},
{
"name": "Tom",
"age": "18",
"gender": "Male"
},
{
"name": "Marry",
"age": "22",
"gender": "Female"
}
]
- [Django]-Django – How to pass several arguments to the url template tag
- [Django]-Django custom management commands: AttributeError: 'module' object has no attribute 'Command'
- [Django]-Django :How to integrate Django Rest framework in an existing application?