Hi Wim, I think there's a slight misunderstanding here. I completely agree with you that .first() and .last() should return None if there's no matching row :). The syntax I proposed:
User.objects.exclude(a=b).filter(c=d).first('id') # Returns None if there's no matching row User.objects.order_by('id').exclude(a=b).filter(c=d).first() # Does the same thing as above Best, Selwin On Wednesday, January 23, 2013 6:03:22 AM UTC+7, Wim Feijen wrote: > > Hi Selwin and Anssi, > > Anssi, thanks for improving the patch and getting it ready for commit! > > Selwin, you are right that .filter() and .first() are very similar. > Rationale for .first() is to get rid of the pattern > try: > instance = ModelX.objects.get > except ObjectDoesNotExist: > instance = None > , which is a very common pattern so an exception seems out of place. Using > filter to get the first result or none would still require three lines. > Other alternative patterns are in this thread. > > For me, example use cases would be Address.objects.first() which would > return the first address in a list, when browsing through all addresses in > detail view, or page.music_files.first() where we just have one music file > per page or none. MusicFile.objects.first(page=page) should work too. > > Indeed, .earliest('timestamp') could be expressed as > .order_by('timestamp').first() , and latest similarly. In my opinion these > are consistent with .filter() and .get(). > > Default ordering by id if no order is specified is the same behaviour as > in the admin, so I would argue not to raise an exception when no ordering > is specified, but to keep it like it is and order by id. Thanks for adding > that Anssi! > > Looking forward to other input, > > Best regards, > > Wim > > > On Sunday, 20 January 2013 12:18:22 UTC+1, Selwin Ong wrote: >> >> Hi Anssi, >> >> Shouldn't first() and last() raise an exception if no ordering is >> specified? This keeps it consistent with latest() which requires the user >> to explicitly specify what field it wants to use as ordering. >> >> Also, like you mentioned, IMHO these APIs are too similar (first, >> earliest, last and latest) in name, yet the usage is completely different, >> with latest() expecting a field name, the other filter args. What I also >> don't like is that the filter_args expected by last() and first() are: >> 1. Doesn't allow exclude arguments >> 2. We already have .filter() method which does the same thing (filters a >> queryset with passed kwargs) >> >> So if I may suggest, I think a better option would be to change the >> methods first() and last() to behave more like latest(), but they should >> return None when the query returns no result. Example usage: >> >> User.objects.exclude(a=b).filter(c=d).first('id') # Returns None if >> there's no match >> >> >> >> user = User.objects.exclude(a=b).filter(c=d).last('id') >> if user: >> # do things... >> >> >> If last() and first() are introduced, perhaps we can also deprecate >> latest() in the future because they're very similar. >> >> What do you guys think? >> >> Best, >> Selwin >> >> On Sunday, January 20, 2013 1:51:27 PM UTC+7, Anssi Kääriäinen wrote: >>> >>> On 10 tammi, 09:27, Wim Feijen <wimfei...@gmail.com> wrote: >>> > Hi, >>> > >>> > Ticket 19326 has been marked as ready for check-in for some time. Can >>> > some-one have a look at it? >>> > >>> > https://code.djangoproject.com/ticket/19326 >>> > >>> > Thanks, >>> > >>> > Wim >>> >>> I did some more polish to the patch. There is now also .last() method, >>> and if there is no ordering in the queryset, then it will be >>> automatically ordered by the primary key. >>> >>> I didn't commit the patch yet, as I wonder if there will be confusion >>> about .latest(by_field), .last(filter_args). earliest(by_field) >>> and .first(filter_args)? >>> >>> Currently, the usage is this: >>> a = >>> Article.objects.order_by('headline').first(pub_date__year=2005) >>> which will return first article by headline if any found or None if no >>> match. .last() will just change the ordering by first >>> calling .reverse() on the qs. >>> >>> The patch is 100% ready for commit as far as I am concerned (cursory >>> check of the changes doesn't hurt, of course). So, if one of the BDFLs >>> sees the API as fine just go and commit the patch. >>> >>> Patch available from >>> https://github.com/akaariai/django/compare/ticket_19326. >>> >>> - Anssi >>> >> -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@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.