3 ms·
The first that came to mind is how `get()` is handled in Django's ORM. The idiomatic way to look for a single object is to use `get`, then catch a `DoesNotExist
by ubercore 5y ago
The first that came to mind is how `get()` is handled in Django's ORM. The idiomatic way to look for a single object is to use `get`, then catch a `DoesNotExist` exception:
From https://docs.djangoproject.com/en/3.2/ref/models/querysets/#get https://docs.djangoproject.com/en/3.2/ref/models/querysets/#...
from django.core.exceptions import ObjectDoesNotExist
try:
blog = Blog.objects.get(id=1)
entry = Entry.objects.get(blog=blog, entry_number=1)
except ObjectDoesNotExist:
print("Either the blog or entry doesn't exist.")
- brianwawok 5y agoRight, but the better way to actually write this is something like entry = Entry.objects.filter(blog__id=1, entry_number=1).first() if entry is None: # deal with does not exist Maybe it's my scala/Java background shining through, but we are big Django users and we ban the "catch exceptions as standard" workflow, because there is almost always a cleaner way...
- zohch 5y ago> Right, but the better way to actually write this is something like Maybe for some cases, but it does not do the exact same thing, see the comment here: https://stackoverflow.com/a/29455777/1598080 https://stackoverflow.com/a/29455777/1598080 And if we are talking about idiomatic, I think it is maybe a stretch to count this as idiomatic for Python, but given it is documented for Django I think it is fair to call it idiomatic for Django.
- ziml77 5y agoThat is the sort of method that I prefer if it's available. I'm a C# dev so this way also feels far cleaner to me.
- _bohm 5y agoThis fails to raise an error if there is more than one object matching the given filters
- notdonspaulding 5y agoPresumably entry_number is unique_together with blog_id. Otherwise the original code is also not handling the MultipleObjectsReturned exception. Generally speaking, I tend toward the cleanest code being: blog = Blog.objects.get(id=1) entry = blog.entry_set.filter(entry_number=1).first() if entry is None: handle_missing_entry() handle_entry(entry) But it does suffer from having the extra DB query in there, which may or may not be helpful, depending on the surrounding code (and whether or not you'll be using the blog instance anywhere else).
- jrochkind1 5y agoWhat are you suggesting is better about that way? More readable?
- dec0dedab0de 5y agoI wouldn't make it an if statement unless it's going to be a part of the standard flow. I think the catchphrase is "leap before you look". Though your right that a single query is better. Honestly, I normally just use get and let the exception fly. If it's a celery task I'll see the stack trace in flower, or right in the output if it's dev with debug on. Then I would go out of my way to make sure there was never a circumstance where a user requests something that doesn't exist.
- louissan 5y agoOr even?: try: blog = Blog.objects.get(slug__icontains='some text') except Blog.ObjectDoesNotExist: print("No blog could be found") except Blog.MultipleObjectsReturned: print('More than one blog!')