On Thursday 28 February 2013, Aymeric Augustin wrote:
> 
> I would support renaming them to first / last through a deprecation path.
> The new aliases would be available immediately, the old ones would be
> removed in two versions.
> 
+1

> And while we're there, I suggest to rely on the existing "ordering" meta
> attribute and to remove "get_latest_by". I suspect that in many cases
> these two attributes have the same value, and you can specify an explicit
> ordering otherwise.

Consistent with the above, +1

and as far as Wim's original question is concerned:

> Which style do you prefer?
> 
> .filter(last_name__startswith='b').order_by('last_name').first()    # clear
> and long
> .first(last_name__startswith='b').order_by('last_name')    # first method
> has filter syntax.
> .filter(last_name__startswith='b').first('last_name')   # first method has
> order_by syntax.

ordering is given by position, filtering by keyword arguments -- why not 
support both?

def first (self, *ordering, **filtering):
        ...

My only concern is one that Anssi raised -- the check for multiple objects is 
discarded, and there is no convenient way to get 0-or-1 objects (which is the 
semantics of the try-get-except-DoesNotExist-return-None pattern this is 
designed to replace). I don't think it has been given enough attention in the 
discussion so far.

One option -- with my suggested syntax -- is that if no ordering is given, 
then it means only one is expected (and, say, None could be used to say "use 
default ordering"). I suspect, though, that this might be a confusing (and 
conflated) interface.

Or maybe it can be saved by saying you must use one or the other but not both; 
then it's "overloaded", but nothing really surprising happens. This way, None 
could be used to say "No ordering -- there should be only one", which is even 
more intuitive. 

We get (semantically):

qset.first('last_name') ==> 
qset.order_by('last_name')[0] if qset.exists() else None

qset.first(None) ==>
qset.get() if qset,exists() else None

qset.first(last_name__startswith='b') ==>
qset.filter(last_name__startswith='b').first(None)

qset.first("last_name", last_name__startswith='b') ==>
raise TypeError("first() takes either all positional args or all keywords")

qset.first() ==>
qset.first(qset.model.ordering)

Note that with this suggestion:

        qset.filter(a=b).first(c)

is not equivalent to

        qset.order_by(c).filter(a=b)

Because the latter checks for multiple objects and the former doesn't; this. 
IMO, justifies raising a type-error when trying to use both.

Shai.

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to