1

I'm looking to sort the results from query sets for django by a certain structure of names and related objects. Order_by() is not viable, since it doesn't accept methods. Making an extra column that hardcodes the name I want isn't practical, and is a workaround for lacking functionality.

I thought to use a custom manager to do this, but I'm having trouble since sorted() always returns a list, and django wants the object to stay as a QuerySet. So, my question is, is there any decent way to use sorted() on a custom class (where the class is basically a list with some extra methods) and get it to remain that custom class? This is actually pretty general, and probably has uses outside of just QuerySets as well.

class ClientManager(models.Manager):
    def get_query_set(self):
        set = super(ClientManager,self).get_query_set()
        return sorted(set, key=lambda a: a.fullName())

As a couple points (and responses to some of the comments here):

  • Documentation on annotate seems to imply that it's limited to aggregation functions. I'd like this to run on a method instead.
  • Caching the value is too much of a workaround for what I'd like to do. Even if it is the best solution from some perspectives, it's not dynamic enough for my taste, and seems to violate DRY in my opinion.

I've seen lots of posts on this subject, it may be that a lack of real sorting capabilities is a shortcoming of django. This sorting is necessary, so that I can make my way through the django admin for tons of data, sorted in a human-understandable way.

Added Question It might be a viable solution if I could turn a list of objects into a QuerySet of objects. Anyone know if this is possible? Specifically, transform it into a <class 'django.db.models.query.QuerySet'> object.

wdahab
  • 347
  • 3
  • 14
  • Have a look at this question and the accepted answer: http://stackoverflow.com/questions/476017/django-queryset-order-by-method – Fred Foo Mar 21 '12 at 14:34
  • Minor nit: It's best not to use names that hide builtin methods, like `dict`, `str`, `list`, or `set`. – Steven Rumbalski Mar 21 '12 at 14:50
  • @larsman I've looked at that, and as far as I can tell, annotate doesn't want to accept methods on the model. It may be that I'm not fully understanding annotate, but all examples I've seen have used functions like Sum or Count, nothing more complicated than that. – wdahab Mar 21 '12 at 15:35
  • @Steven Yeah I know, I'd just forgotten that set was a builtin when writing the example. Thanks, though. – wdahab Mar 21 '12 at 15:36

1 Answers1

0

Assuming you have such a model:

class YourModel(models.Model):
    # fields

    def fullName(self):
        # return the fullName

Then you should cache the fullName in a database column, and keep it fresh with a signal, as such:

from django.db.models import signals

class YourModel(models.Model):
    # fields

    # cointains the return value of make_fullName
    fullName = models.CharField(max_length=100)

    def make_fullName(self):
        # return the fullName

# update YourModel fullName before saving:
def update_fullName(sender, instance, **kwargs):
    instance.fullName = instance.make_fullName()
signals.pre_save.connect(update_fullName, sender=YourModel)

Then, you can order_by('fullName')

jpic
  • 32,891
  • 5
  • 112
  • 113
  • Using my example above, fullName() uses fields in some related models. Using signals to update cached values gets a bit complicated when having to account for changes in those related fields. – wdahab Mar 21 '12 at 15:30
  • It can be "a bit" complicated to add another similar signal for related models. It will be "pretty" complicated to voodoo the manager and/or queryset. Also, using sorted() on a queryset executes it, so I don't understand why you want to sorted() and get a queryset rather than a list. – jpic Mar 21 '12 at 16:46
  • the django-admin. Easy to view/edit information, not easy to get it to show it you the data in an easily navigable way. – wdahab Mar 21 '12 at 19:14
  • btw, I did end up doing this. That doesn't mean I have to like it. :) – wdahab Mar 21 '12 at 20:42