2

I'm trying to order by a count of a manyToMany field is there a way to do this with TastyPie?

For example

class Person(models.Model):
    friends = models.ManyToMany(User, ..)

I want PersonResource to spit out json that is ordered by the number of friends a person has...

is that possible?

9-bits
  • 10,395
  • 21
  • 61
  • 83

3 Answers3

2

I know this is an old question, but I recently encountered this problem and came up with a solution.

Tastypie doesn't easily allow custom ordering, but it is easy to modify the queryset it uses. I actually just modified the default queryset for the model using a custom manager.

for instance:

class PersonManager(models.Manager):
    def get_query_set(self):
        return super(PersonManager self).get_query_set().\
            annotate(friend_count=models.Count('friends'))

class Person(models.Model):
    objects = PersonManager()
    friends = ...

You could also add the annotation in Tastypie, wither in the queryset=... in the Meta class, or overriding the get_object_list(self,request) method.

coaxmetal
  • 33
  • 1
  • 7
2

I wasn't able to get the results ordering as per coaxmetal's solution, so I solved this a different way, by overriding the get_object_list on the Resource object as per http://django-tastypie.readthedocs.org/en/latest/cookbook.html. Basically if the 'top' querystring parameter exists, then the ordered result is returned.

class MyResource(ModelResource):
    class Meta:
        queryset = MyObject.objects.all()

    def get_object_list(self, request):
        try:
            most_popular = request.GET['top']
            result = super(MyResource, self).get_object_list(request).annotate(num_something=Count('something')).order_by('num_something')
        except:
            result = super(MyResource, self).get_object_list(request)
        return result
nosforz
  • 39
  • 4
0

I have not used TastyPie, but your problem seems to be more general. You can't have custom ordering in a Django ORM query. You're better off storing tuples of the form (Person, friend_count). This is pretty easy:

p_list = []
for person in Person.objects.all():
    friendcount = len(person.friends.all())
    p_list.append((person, friendcount))

Then, you can use the built in sorted function like so:

sorted_list = [person for (person, fc) in sorted(p_list, key=lambda x: x[1])]

The last line basically extracts the Persons from a sorted list of Persons, sorted on the no of friends one has.

`

yati sagade
  • 1,355
  • 9
  • 24