Opened 16 years ago
Closed 14 years ago
#11352 closed New feature (wontfix)
get_object/list_or_none methods
| Reported by: | Chuck Harmston | Owned by: | nobody |
|---|---|---|---|
| Component: | Core (Other) | Version: | dev |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Design decision needed | |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Hey all,
First time contributor (not just to Django, but to any open source project), so go easy on me.
Several times I've found myself wanting for a get_list_or_none() shortcut method. get_list_or_404 is nice, but there are some instances (search results, for example) where returning an empty QuerySet makes much more sense. Attached is a patch adding functional get_list_or_404 and get_object_or_404 methods to django.shortcuts. I am aware that in #2659 Adrian rejected get_object_or_404 as scope creep, but since that time objects.none() has been introduced, which would render these methods much more useful. Feel free to set it as wontfix if you still think it's scope creep, but these are certainly useful methods for me, and I'm sure they would be for others as well.
I have not run unit tests on this; it seems to me that it would make more sense to get community buy-in on the necessity for these methods first.
Feedback welcome. Thanks all!
Attachments (3)
Change History (12)
by , 16 years ago
| Attachment: | object_list_404.diff added |
|---|
comment:1 by , 16 years ago
| Needs tests: | set |
|---|
comment:2 by , 16 years ago
| Patch needs improvement: | set |
|---|
comment:3 by , 16 years ago
| Summary: | get_object/list_or_404 methods → get_object/list_or_none methods |
|---|
Whoops, obvious oversight! I forgot to wrap list() around the return value for get_list_or_none().
by , 16 years ago
| Attachment: | object_list_404-2.diff added |
|---|
Modification: wraps get_list_or_none() return value in list()
comment:4 by , 16 years ago
| Triage Stage: | Unreviewed → Design decision needed |
|---|
comment:5 by , 16 years ago
| Needs tests: | unset |
|---|---|
| Patch needs improvement: | unset |
Added a new patch with proper documentation and unit tests.
Sidebar: it may be worth considering renaming tests/get_object_or_404 to something like tests/dbapi_shortcuts.
comment:6 by , 16 years ago
Returning a list from get_object_or_none makes no sense to me, it should return None .
comment:7 by , 15 years ago
| Severity: | → Normal |
|---|---|
| Type: | → New feature |
comment:8 by , 14 years ago
| Easy pickings: | unset |
|---|---|
| UI/UX: | unset |
I'm having a hard time understanding the rationale behind this feature. This pattern seems rather obscure, rather than so commonplace so as to warrant a shortcut method.
You can already do this quite succinctly:
query_set = Book.objects.filter(pk=999) val = query_set.get() if query_set else Book.objects.none()
(This assumes that your query set may return one or no results. A larger result set will cause a MultipleObjectsReturned exception to be raised.)
It's possible I'm missing something obvious, but I can't help the feeling that having functions that expect a model instance or an empty QuerySet is an anti-pattern. A QuerySet is a collection; an empty QuerySet is still just an empty collection. Alex's proposal (that get_object_or_none return None instead) is more palatable, but I think that in order for this to be compelling a realistic use-case ought to be presented.
comment:9 by , 14 years ago
| Resolution: | → wontfix |
|---|---|
| Status: | new → closed |
I agree with Ori that I can't see the rationale for these:
1) get_object_or_none is unhelpful - it returns either a single object or an empty QuerySet, which means you then still need to test what type of thing you've got i.e. a list of things or a single thing, which I agree seems to promote an anti-pattern. If you just want to silence the DoesNotExist you get from the get() call if there are no matching items - don't use get(), just use list() on the QuerySet. The only other case this function would be useful is if you want an empty list for the case where get() returns zero items or it returns more than 1 item, but you want a single object if it returns exactly 1 item. This is certainly not a common case in my experience.
2) get_list_or_none seems even more bizarre. This method just seems to be a rather inefficient way of doing list(queryset.filter(**kwargs)) - list(queryset.none()) is always exactly equal to an empty list, and empty lists are empty lists. (It's also incorrectly documented as having something to do with DoesNotExist exceptions).
I think these things must be based on some misconception about how lists in Python work, or something, I'm afraid I can't work out the intention here.
Adds get_list_or_none and get_object_or_none methods to django.shortcuts