Marcelo
Marcelo

Reputation: 429

Ordering by many to many attribute on Django Rest Framework

I have a table of TransportationOrders. Every TransportationOrder has a Route.. and every Route has Places.

What I need is lo list All the TransportationOrders but sorted by the name of the first place I have to visit.

My Models simplified:

class TransportationOrder(models.Model):
    name = models.CharField(max_length=45, unique=True)
    user = models.ForeignKey('auth.User')
    description = models.CharField(max_length=300, blank=True, null=True)
    route = models.ManyToManyField(Place, through='PlaceHasTransportationOrder')


class PlaceHasTransportationOrder(models.Model):
    place = models.ForeignKey(Place, on_delete=models.CASCADE)
    transportation_order = models.ForeignKey(TransportationOrder, related_name="route", on_delete=models.CASCADE)
    order = models.IntegerField(default=1) #This indicate the order of  visits
    date = models.DateField()

class Place(models.Model):
    name = models.CharField(max_length=45)
    address = models.CharField(max_length=45, null=True, blank=True, default=None)
    lat = models.FloatField(null=True, blank=True, default=None)
    lon = models.FloatField(null=True, blank=True, default=None)

I tried to define a method on TransportationOrder Model, but this doesn't work whe I try to http:///url?ordering=first_place_name because this ordering works on a database level. What option do I have?

def first_place_name(self):
    place = Place.objects.all().filter(placehastransportationorder__transportation_order=self, placehastransportationorder__order=1)
    return place[0].name

Upvotes: 1

Views: 587

Answers (1)

gallen
gallen

Reputation: 1292

Try using the order_by method of Django QuerySets. I believe what you want is

TransportationOrder.order_by('routes__name').first()

or something similar.

As an example, I loaded your models into a one off using Django 1.10.5.

I created 5 objects: p and p2 are Place entries, t is a TransportationOrder, and pt & pt2 are PlaceHasTransportationOrder entries.

p was related to t, and p2 was related to pt2. The TransportationOrder object t was used on both pt and pt2.

I named the Place's "Testing" and "Alphabet", creating "Alphabet" second. This made it so that just a basic query on the routes field of TransportationOrder would return them in id order:

t.first().routes.all().values_list('name') <QuerySet [('Testing',), ('Alphabet',)]>

Applying the order_by I mentioned above resulted in:

t.order_by('routes__name').values_list('routes__name') <QuerySet [('Alphabet',), ('Testing',)]>

EDIT:

The output from the last statement lists the TransportationOrder objects in order by their Place names. I mistakenly narrowed the output to only output the values of the routes__name relationship pathway.

Upvotes: 1

Related Questions