tcpiper
tcpiper

Reputation: 2554

Django 1.6 how to first filter according to another model, then order the model?

Ok, the order fields in Question is dynamic. Not only 'votes', depend on which field user choose.

If there are two models:

class Question(models.Model):
    user = models.CharField()  
    title = models.CharField()  
    content = models.TextField()
    votes = models.SmallIntegerField(default=0)
    create_time = models.DateTimeField(auto_now_add=True)
    last_edit_time = models.DateTimeField(auto_now=True)

class Label(models.Model):
    question = models.ForeignKey(Question)  
    create_time = models.DateTimeField(auto_now_add=True)  
    name = models.CharField(max_length=10)

An question may have many labels. if I want to get all questions whose label_set has a label named 'python', then order these questions by 'votes' or by 'create_time' or any other field. How to? This is what I tried:

res=[]
for question in Question.objects.all():
    if 'python' in question.label_set.all():
        res.append(question)

But then how to order res by 'vote'? I've read the tutorial but no results. Plus, I feel this way not the best way. Which way is the best?

Is there a way like:

Question.objects.filter(label_set__contains='python').oder_by('votes')

I really hope...

Upvotes: 0

Views: 92

Answers (2)

Mp0int
Mp0int

Reputation: 18747

You can make a list of filtering criteria with ordering information as a list

order_crit = {
    'python': ['votes'],
    'django': ['create_time', 'votes']
}

You can use `*` to unpack values in a list like

Question.objects.filter(label__name__contains=filter_crit).oder_by(*order_crit[filter_crit])

So if you wish to filter them by python

filter_crit = 'python'
Question.objects.filter(label__name__contains=filter_crit).order_by(*order_crit[filter_crit])

Following will result in following:

Question.objects.filter(label__name__contains='python').order_by('votes')

Because * will unpack your list as argument values within order_by. You can use multiple fields for ordering by adding the fields to the lists in order_crit

Upvotes: 1

user2707389
user2707389

Reputation: 827

One option would be to make a meta class inside the mode (doc here) :

e.g.:

class Question(models.Model):
    user = models.CharField()  
    title = models.CharField()  
    content = models.TextField()
    votes = models.SmallIntegerField(default=0)

    class Meta:
        ordering = ['votes']

Also for making queries, you do not need to make array and append yourself. Django provides a lot of ways to make queries. Read here.

Upvotes: 0

Related Questions