2

I have a following model:

class Mountain(models.Model):
    name = CharField(max_length=200)

class Climbing(models.Model):
    mountain = models.ForeignKey(Mountain)
    climber = CharField(max_length=200)
    date = models.DateField(auto_now_add=True)

I want to group climbings by mountains and sort mountains by last climbing, also as sort climbings inside each mountain.

Everest:
    2018-12-21
    2018-10-10
    2000-01-30

K2:
    2018-12-20
    2018-11-30

the same in code:

(
    [
        'everest',
        ['2018-12-21', '2018-10-10', '2000-01-30']
    ],
    [
        'K2',
        ['2018-12-20', '2018-11-30']
    ]
)

What is the most effective way to implement it in Django but on side of database? I understand i can make a set of climbings, filter by related mountains etc, but i would like to make all calculations on postgres server.

Alex Zaitsev
  • 690
  • 6
  • 17
  • please provide some sample input and output as you expect that will help other to reach your problem. – R.A.Munna Dec 21 '18 at 01:55
  • @R.A.Munna something like: (['everest', ['2018-12-21', '2018-10-10', '2000-01-30']], ['K2', ['2018-12-20', '2018-11-30']]) – Alex Zaitsev Dec 21 '18 at 08:36

1 Answers1

3

I don't understand why you would want to do calculations on Postgres where Django provides efficient solution through ORM?

BTW, you can achieve the data by using order_by via Django ORM:

Climbing.objects.all().order_by('-date', 'mountain__name')

FYI, its a lazy query and won't even hit the database(so efficiency should not be a problem) and you will get data when you evaluate the Queryset.

Update

Try like this:

Update the models like following:

    class Mountain(models.Model):
        name = CharField(max_length=200)


    class Climbing(models.Model):
        mountain = models.ForeignKey(Mountain, related_name="climbings")  # <-- Here
        climber = CharField(max_length=200)
        date = models.DateField(auto_now_add=True)

        class Meta:
           ordering = ('-date',)  # <-- Here

Then use prefetch_related to fetch the related objects.(docs)

from django.db.models import Prefetch

prefetch = Prefetch('climbings', Climbing.objects.all())

# OR
# prefetch = Prefetch('climbings', Climbing.objects.only('date'))

mountains = Mountain.objects.all().prefetch_related(prefetch).order_by('name')

for m in mountain:
    print(m.name)
    print(m.climbings.all().values_list('date', flat=True))

# Or
mountains.values('name', 'climbings__date')  # or user values_list if you want it as a list

Update 2

For sorting by latest date of climbing, try like this:

mountains = Mountain.objects.all().prefetch_related(prefetch).annotate(max_date=Max('climbings__date').order_by('max_date')
ruddra
  • 50,746
  • 7
  • 78
  • 101