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 django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
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