class Tag(models.Model):
name = models.CharField(maxlength = 50, unique = True)
parent = models.ForiegnKey('self', related_name='child',
null = True, blank = True)
class Meta:
ordering = ['parent', 'name']
def __str__(self):
if self.parent_id is not None:
prefix = str(self.parent) + '/'
else:
prefix = ''
return prefix + self.name
Now, this model almost, but not quite, orders the tags in a "natural"
fashion. That is, if I have a tag structure that looks like this:
Life
Universe
Everything
Software
Python
Django
Design
Theory
I will get an ordering of:
Life
Software
Life/Everything
Life/Universe
Software/Design
Software/Python
Software/Design/Theory
Software/Python/Django
(actually, for some reason that I don't yet understand and suspect is a
bug, I don't get the ordering in the admin list view, but it does get
ordered that way in select boxes and stuff that I care about. Let's
ignore that for now.)
What I really want is for the ordering to have sub-categories under the
parent category. This would be easy if I could sort on the str() value
for each object, since the natural ordering is the lexicographic
ordering of the strings. Is there an easy way to do this? I seem to have
come across it a few times now (I like hierarchies, so sue me).
Unfortunately, Meta.ordering seems to want a real field, not a method
(which Admin.list_display can take) or a property.
So am I missing something, or is this even a common need for other
people?
Malcolm
> Unfortunately, Meta.ordering seems to want a real field, not a method
> (which Admin.list_display can take) or a property.
>
> So am I missing something, or is this even a common need for other
> people?
Meta.ordering does ordering in the database using an SQL 'ORDER BY'
clause, so you can't use a function defined in your model to do that
ordering.
A solution (or part of one) is available in magic-removal. You can
create your own custom manager, and it has a method get_query_set that
you can override. You could then create a subclass of QuerySet that
has certain methods overridden to do ordering after the data is
returned. (I think the one you'd need to override is
QuerySet._get_data).
The first 'Manager' to be defined is used as the default one, so your
custom manager would work in the Admin and elsewhere.
There may still be issues in getting this to play well with other
ordering, I'm not sure, but they should be fixable.
Luke
--
"The first ten million years were the worst. And the second ten
million, they were the worst too. The third ten million, I didn't enjoy
at all. After that I went into a bit of a decline." (Marvin the
paranoid android)
Luke Plant || L.Plant.98 (at) cantab.net || http://lukeplant.me.uk/