try:
user = User.objects.get(pk=user_id)
except User.DoesNotExist:
user = None
What do you think about adding a get_or_none QuerySet method?
def get_or_none(self, **kwargs):
try:
return self.get(**kwargs)
except self.model.DoesNotExist:
return None
Or how about using something similar to QuearyDict's get(key,
default)? That way the fallback is not restricted to `None`. So
something like this:
user = User.objects.get(pk=user_id, default=None)
Of course, I think that would probably be significantly more work than
your little wrapper function.
--
----
Waylan Limberg
way...@gmail.com
note neccessarily (beware, quick&ugly proof of concept):
Index: django/db/models/query.py
===================================================================
--- django/db/models/query.py (revision 4227)
+++ django/db/models/query.py (working copy)
@@ -12,6 +12,8 @@
# The string constant used to separate query parts
LOOKUP_SEPARATOR = '__'
+# for get(default)
+NOT_SET='WHATEVER'
# The list of valid query types
QUERY_TERMS = (
@@ -202,7 +204,8 @@
cursor.execute("SELECT COUNT(*)" + sql, params)
return cursor.fetchone()[0]
- def get(self, *args, **kwargs):
+
+ def get(self, default=NOT_SET, *args, **kwargs):
"Performs the SELECT and returns a single object matching the
given keyword arguments."
clone = self.filter(*args, **kwargs)
# clean up SQL by removing unneeded ORDER BY
@@ -210,6 +213,8 @@
clone._order_by = ()
obj_list = list(clone)
if len(obj_list) < 1:
+ if default != NOT_SET:
+ return default
raise self.model.DoesNotExist, "%s matching query does
not exist." % self.model._meta.object_name
assert len(obj_list) == 1, "get() returned more than one %s
-- it returned %s! Lookup parameters were %s" %
(self.model._meta.object_name, len(obj_list), kwargs)
return obj_list[0]
> --
> ----
> Waylan Limberg
> way...@gmail.com
>
> >
>
--
Honza Král
E-Mail: Honza...@gmail.com
ICQ#: 107471613
Phone: +420 606 678585
Except this would break (or at least limit the functionality of)
objects which use "default" as a field name.
Now I know why. Good call SmileyChris. Unfortunately I have no ideas
for a workaround.
Of course, this didn't stop get_or_create(), which uses "defaults" as a
parameter. If you had an object with an attribute named "default" then
you could still do something like:
obj = MyModel.objects.get(default__exact=42, default=None)
But get_or_create() was new functionality and this would be changing
existing functionality. If that is unacceptable, then maybe a
get_or_default() that optionally takes the "default" parameter, using
None if no "default" specified.
So...
MyModel.objects.get_or_default(pk=1)
would be equivalent to
MyModel.objects.get_or_default(pk=1, default=None)
SmileyChris wrote:
> On Dec 19, 11:08 am, "Waylan Limberg" <way...@gmail.com> wrote:
> > something like this:
> >
> > user = User.objects.get (pk=user_id, default=None)
+1
On 12/20/06, Joseph Perla <josep...@gmail.com> wrote:
> There should also be an update_or_create() function.
+1
This gave me the idea of an update() method for model instances. I
have created a ticket for this with code, documentation, and tests.
I have created a ticket for this too and have attached some code:
Documentation and tests attached too now.
Hm - I get a whole bunch of failures when I apply the patch. Looking closer,
you say it depends on an ``update()`` patch in #3181, but I don't see any such
patch attached to #3181.
Can you update #3182 to include this other patch (wherever it lives), and
close the other ticket as a dup of #3182? Once that's done I'll go ahead and
check this in.
Jacob
Sorry about that, it should be #3180.
> Can you update #3182 to include this other patch (wherever it lives), and
> close the other ticket as a dup of #3182? Once that's done I'll go ahead and
> check this in.
Well, the two tickets are different functionality. I could create a
single patch for both, the only thing was that in the patch for #3180 I
added an "Updating objects" to the db api documentation, but then
realized that it should probably be integrated into the "Saving changes
to objects" section. I haven't spent the time to do that yet.
Yeah, they're different... but I think they make the most sense if they go in
as a unit. I'd prefer a single patch (and tests, docs, etc.) if you're up to it.
Jacob
Sure, I'll work on the documentation fixes and let you know when done.
Ok. I reworked the documentation, rolled both patches into one, and
attached it to #3182.
1) Add a get_or_none() method that returns None if object does not
exist.
2) Add a get_or_default() method that accepts a "default" keyword
argument, the value of which gets returned if object does not exist.
If a default is not specified then None gets returned by default.
3) Modify the current get() method to accept a "default" keyword
argument as in option 2), except that instead of returning None if
"default" is not specified, a DoesNotExist exception is raised like
normal. To return None, you would have to explicitly say
"default=None".
Note that this would also be backwards incompatible in that models with
a field named "default" would have to use "default__exact=..." instead
of "default=..." as with get_or_create(). Looking further, it looks
like functions that use get() might also have to change slightly, i.e.
get_or_create().
Comments/votes/suggestions?
Any other requests for the new, combined patch?
I tested the patch and it works as advertised, also the docs are well
written. This is functionality I'm looking forward to.
<http://code.djangoproject.org/ticket/3182>
Thanks!
- whiteinge
It will probably be applied at some point. It is one of a number of open
tickets. Sorry, but there are lots of things we want to work on all at
the same time.
Malcolm