> I'm not the first to suggest adding an additional shortcut, e.g. django.shortcuts.get_object_or_none which would work similarly to get_object_or_404
Personally I'm not a fan of it being in "shortcuts". It makes sense to me that the 404 ones are there because they are only useful in a request/response lifecycle. Seems like a good call to keep that out of the standard queryset methods. But `get_or_none` could be used anywhere, and ergonomically (?) it makes more sense to me that people (especially people new to Django) would naturally find and use it if it were right next to `get` and `get_or_create` (in docs, autocomplete, search in your codebase, etc.). > I believe the main objection is against adding additional API to querysets. Yeah, I hope I'm not coming off as being too pushy, but I'm just curious why that is. Mariusz or Adam, did what I said about it being *more* than just an alias for `filter().first()` make sense or am I missing something? (Different behavior for multiple results — on accident or otherwise) Dave On Monday, July 11, 2022 at 1:06:04 AM UTC-5 m...@feinheit.ch wrote: > Hi > > I believe the main objection is against adding additional API to > querysets. get_object_or_404 only converts DoesNotExist into a 404 > exception and doesn't handle MultipleObjectsReturned. > > I'm not the first to suggest adding an additional shortcut, e.g. > django.shortcuts.get_object_or_none which would work similarly to > get_object_or_404 (and get_list_or_404 for that matter). The existing > shortcuts use functionality from several parts of Django (the ORM and the > request/response handling) which get_object_or_none wouldn't do, but its > behavior would be so close to what get_object_or_404 is doing that it may > be alright. > > OTOH even the implementation of this shortcut is so simple that I just add > it to each project when I have a need for it (I had a hard time finding it > because it comes up much less often than I thought it did). So I am not > proposing this addition personally but I wouldn't be against it either (if > that counts for anything). > > Best regards, > Matthias > > > > def get_object_or_none(klass, *args, **kwargs): > 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_404() must be a Model, > Manager, " > "or QuerySet, not '%s'." % klass__name > ) > try: > return queryset.get(*args, **kwargs) > except queryset.model.DoesNotExist: > return None > > > > On Sun, Jul 10, 2022 at 10:13 PM Dave Gaeddert <dave.g...@gmail.com> > wrote: > >> Fair enough. To me, the `get_or_none` behavior with multiple results >> would still be to raise an exception (so it is just like `get` in that >> sense). And that’s the reason I personally don’t just see it as a shortcut >> for `filter().first()` — I have (as I’m sure others have) made the mistake >> before of *thinking* that I was using a unique query when that wasn’t >> necessarily true, so the multiple results exception has caught mistakes at >> runtime. I’d rather have that exception than use `filter().first()` and >> potentially show the wrong object to the wrong user, for example, and not >> figure out that I have a uniqueness/db problem. I like the fact that `get` >> raises those exceptions, I just think that try/except DoesNotExist/None is >> such a common behavior that a shortcut for *that* would actually be >> useful. >> >> Dave >> On Sunday, July 10, 2022 at 3:24:32 AM UTC-5 Adam Johnson wrote: >> >>> I'm also against adding get_or_none(), for the same reasons. Adding a >>> method to shortcut something that can already be done doesn't seem worth it >>> to me. >>> >>> On Sat, Jul 9, 2022 at 1:56 PM Mariusz Felisiak <felisiak...@gmail.com> >>> wrote: >>> >>>> I'm against it because it's already easily achievable and it's >>>> debatable how it should behave with many results. IMO any new method would >>>> be confusing and in the case of unique filtering >>>> `get_or_none(unique_filters)` would be an alias for >>>> `.filter(unique_filters).first()`. To me, this is duplication of an API. >>>> >>>> There are several -0 in the previous thread (Shai, Florian) and you can >>>> count -1 from me. >>>> >>>> Best, >>>> Mariusz >>>> >>>> -- >>>> You received this message because you are subscribed to the Google >>>> Groups "Django developers (Contributions to Django itself)" group. >>>> >>> To unsubscribe from this group and stop receiving emails from it, send >>>> an email to django-develop...@googlegroups.com. >>>> To view this discussion on the web visit >>>> https://groups.google.com/d/msgid/django-developers/aeb9be96-ec03-48f9-ae97-2859b62a1df6n%40googlegroups.com >>>> >>>> <https://groups.google.com/d/msgid/django-developers/aeb9be96-ec03-48f9-ae97-2859b62a1df6n%40googlegroups.com?utm_medium=email&utm_source=footer> >>>> . >>>> >>> -- >> You received this message because you are subscribed to the Google Groups >> "Django developers (Contributions to Django itself)" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to django-develop...@googlegroups.com. >> > To view this discussion on the web visit >> https://groups.google.com/d/msgid/django-developers/dbee041d-4f80-4e61-bf0a-1d6f4e2e22e6n%40googlegroups.com >> >> <https://groups.google.com/d/msgid/django-developers/dbee041d-4f80-4e61-bf0a-1d6f4e2e22e6n%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> > -- You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-developers+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/b150453f-1b96-4475-af21-2d4242fd0758n%40googlegroups.com.