views:

1781

answers:

2

I have a handful of records that I would like to sort based on a computed value. Got the answer over here... like so:

sorted (Profile.objects.all (), key = lambda p: p.reputation)

on a Profile class like this:

class Profile(models.Model):

    ...

    @property
    def reputation(self):
        ...

Unfortunately the generic view is expecting a queryset object and throws an error if I give it a list.

Is there a way to do this that returns a queryset

or...

Can I convert a list to a queryset somehow? Couldn't find anything like that in the django docs.

I am hoping not to denormalize the data, but I guess I will if I have to.

update

it seems that the only way to get a queryset back is if you can get all of your logic into the sql queries. When that is not the case, (I think) you need to denormalize the data, unless there is some way to convert the sorted list back into a queryset

+5  A: 

There is no point in converting a data list back to a query. A query object never holds data; it just represents a query to the database. It would have to fetch everything again if you made your list to a query, and that would be redundant and very bad performance-wise.

What you can do:

  • Describe how the reputation field is calculated; it's probably possible to order the data in the database somehow.
  • Modify the view to not require a query object. If it needs to do additional filtering etc. this should be done before any ordering, since the ordering will take less time with less entries (and less data will be fetched from the database.) So you could send the filtered query object to the sort function just before you send it to the template (which shouldn't care whether it's a query or a list.)
Blixt
reputation is a property, not a field... so that is not valid
Jiaaro
Well in that case, you should either store it as a field (redundant data is not always bad if it helps performance, even in normalized databases) or you should order by something else. I'm assuming it's a calculated or joined field, and you can sort by those too with the Django database model.
Blixt
just had an idea... since the generic view wants to do some kind of filtering, why don't I just do the sorting with a template tag?
Jiaaro
If you don't have access to the view, and cannot wrap it or in some other way affect the query set before it is sent to the template, then that is certainly an alternative. I don't know if the dictsort filter is implemented to support model instances, but if it isn't you can always make your own.
Blixt
+2  A: 

Turns out the answer can be found on stack overflow (if you know how to look for it)

http://stackoverflow.com/questions/476017/django-queryset-order-by-method

Jiaaro
the django aggregation probably won't solve your problem, since reputation is not field (hence there is no column in table for it), reputation is property.
SashaN
so it's looking like I have to denormalize?
Jiaaro
Describe your models in more detail in your question; especially how the 'reputation' field is calculated.
Blixt
@Blixt reputation was just an example in the other question that lead to this question. I'm actually dealing with django-voting
Jiaaro