About Ordering by the Extra Fields of Many-to-many Relations

In the queryset with many-to-many relation through a custom model, you can access the through models fields

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
>>> from django.utils.timezone import now
>>> from readinglist.models import Book, Reader, BookToRead
>>> book = Book.objects.create(
...    title="Django 3 Web Development Cookbook", 
...    authors="Aidas Bendoraitis, Jake Kronika")
>>> reader = Reader.objects.create(name="Wannabe Djangonaut")
>>> reader.reading_list.add(book, through_defaults={
...    "priority": 1, "added_date": now()})
>>> qs1 = Book.objects.filter(
....    booktoread__reader=reader).order_by("booktoread__priority")
>>> qs2 = reader.reading_list.order_by("booktoread__priority")
>>> str(qs1.query) == str(qs2.query)
True

Here the models of the readinglist app are defined as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=200)
    authors = models.CharField(max_length=200)

    def __str__(self):
        return self.title

class Reader(models.Model):
    name = models.CharField(max_length=200)
    reading_list = models.ManyToManyField(
        Book, through="BookToRead", through_fields=("reader", "book")
    )

    def __str__(self):
        return self.name

class BookToRead(models.Model):
    book = models.ForeignKey(Book, on_delete=models.CASCADE)
    reader = models.ForeignKey(Reader, on_delete=models.CASCADE)
    priority = models.PositiveIntegerField()
    added_date = models.DateTimeField()

    def __str__(self):
        return f"{self.reader} wants to read {self.book}"

Tips and Tricks Programming Development Databases Django 4.2 Django 3.2 Django 2.2 PostgreSQL MySQL SQLite