Marla
Marla

Reputation: 101

django: order a QuerySet

I have a view like this:

def profile (request):
    articles = Post.thing.all()
    newSet = set()
    def score():
        for thing in articles:
            Val = some calculation...
            ....
            newSet.update([(thing,Val)])      
    score()
    context = {
     'articles': articles.order_by('id'),
     'newSet':newSet,
    }
    return render(request,'my_profile/my_profile.html',context)

and the outcome is a Queryset which looks like this:

set([(<thing: sfd>, 1), (<thing: quality>, 0), (<thing: hello>, -1), (<thing: hey>, 4), (<thing: test>, 0)

I am now trying to order the set by the given Values so its a list which starts with the highest Value, but when i do newSet.order_by/filter/split/join it does not work since 'set' object has no attribute join/filter/split.

Can anybody give me a hint how to sort the querySet i could not find anything helpful on my own.

I need this to work out in the view so it cannot/should not be done in the model. Thanks for any advise.

Upvotes: 0

Views: 1094

Answers (2)

FraserES
FraserES

Reputation: 356

I think you might be slightly confused here between a set, a list and a QuerySet? A set is unordered, while a list is not. Sets don't expose the methods you listed above (filter, order_by, split, join). A QuerySet is a Django-specific class which has many useful methods.

I think it would be simpler to make newSet a list of tuples, and then to order that list by value using list.sort(key=lambda x: x[1]).

If your calculation of val is eligible for it though, I'd recommend using annotate and then doing away with newDict or newSet, and simply pass back the queryset of articles, which would be much simpler, maybe faster, and orderable by using articles.order_by('value'). If you post the calculation of val, I'll try to tell you if that's feasible.

Upvotes: 1

bruno desthuilliers
bruno desthuilliers

Reputation: 77942

the outcome is a Queryset which looks like this

Actually this is a set (python builtin type), not a QuerySet (django's orm type).

set is an unordered collection type. To "sort" it you first have to turn it into a list - which is actually as simple as newlist = list(newset), then you can sort the list in-place with newlist.sort(). Since you want this list to be sorted on it's items second elements, you'll need to use the key argument to tell sort on what you want to sort:

newlist.sort(key=lambda item: item[1])

or you can just change your score() function to store (score, obj) tuples instead in which case list.sort() will naturally do the RightThing (it will sort your tuples on their first item).

While we're at it: instead of calling newSet.update() with a list of a single item, you can just use newSet.add() instead, ie:

def score():
    for thing in articles:
        val = some calculation...
        ....
        newset.add((thing, val)) 
        # or if you don't want to specify a callback
        # for `list.sort()`:
        # newset.add((val, thing))

And finally: do you really need a set at all here ? Why not using a list right from the start ?

Upvotes: 1

Related Questions