How to custom sort a Django queryset
Question: Given a data model with Title strings, say:

    
    
    class DVD(models.Model):
        title = models.CharField(max_length=100)
    class DVDAdmin(admin.ModelAdmin):
        ordering = ('title',)
    
    sample_titles = {"A Fish Called Wanda", "The Good, the Bad, and the Unsorted",
                     "A River Runs Upstream", "The Incredibles",}
    

I want to generate a queryset sorted by title, but considering the title as
minus any leading words that are in a list, such as ("a", "an", "the",). So
"The Incredibles" would sort before "A River Runs Upstream", etc. I don't want
to just _truncate_ the data, either in the database or in the resulting view.
I want to create an internal custom sort for querysets.

One approach that seems like it _might_ work, is to create a custom
Changelist, then sort the queryset there, as:

    
    
    from django.contrib.admin.views.main import Changelist
    class title_sortlist(Changelist):
        def apply_special_ordering(self, queryset):
            qs_desc = self.models.objects.all().order_by('-title')
            return qs_desc
        def get_query_set(self, request, *args, **kwargs):
            queryset = super(title_sortlist, self).get_query_set(request)
            queryset = self.apply_special_ordering(queryset)
            return queryset
    
    class DVDAdmin(admin.ModelAdmin):
        ordering = ('title',)
        def get_changelist(self, request, **kwargs):
            return title_sortlist
    

This works for standard sorting - the descending sort does override the
model's ascending sort. However, I haven't figured out how take a queryset and
custom sort it.

Another possibility might be to _dynamically_ add a field to the model, call
it _cut_title_ , suitably edited, then just sort by that field. However, I've
just starting reading about dynamic model changes, and it's not clear how to
do it (not to mention, it seems slightly wonky, more so than regular monkey-
patching).

A third option, I was reading that Django has an `extra` option for querysets,
where you can add additional SQL, including new fields. I have no idea how to
add a new SQL field that represents the edited title, though - can Django SQL
call a Python function, maybe?

So what approach, if any, would be best for sorting a queryset by (modified)
title?


Answer: @bebraw in the comments is actually right.

Creating a special sort field is how it is done. This is custom for search
frameworks like SOLR, as well. You even might apply special text analysis to
sort according to language.

In your case, if it's just as simple as to remove the stop words (a short list
of articles), you would create a regular model field that copies the data from
the other field and removes the stop words.

The benefit from using a regular DB field: you can create a DB index (e.g. on
UPPER(value)) and be able to sort case insensitive supported by the DB index
(you will have to add an extra field with QuerySet.extra to sort on
UPPER(value)).

This will allow fast sorted and paged results. If you do everything in Django
you will have to retrieve the whole data. This might be fast enough for some
hundreds of rows but will not scale at all if the data increases.

HOWEVER: Be careful with stop words depending on your data. The anti example
to stop words is the title "To Be or Not To Be" which consists completely of
what you might easily classify as stop words and would simply be annihilated
when running through such a filter.

