Reputation: 6527
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?
Upvotes: 1
Views: 5088
Reputation: 16661
@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.
Upvotes: 1