Для связей m2m автоматически создаётся промежуточная модель, содержащая лишь два поля для связи с обоими таблицами. Эту модель можно создать явно, указав дополнительные поля:
class Course(models.Model):
name = models.CharField()
programs = models.ManyToManyField('Program', through='ProgramCourse', related_name='courses')
class Program(models.Model):
name = models.CharField()
class ProgramCourse(models.Model):
program = models.ForeignKey(Program, on_delete=models.CASCADE)
course = models.ForeignKey(Course, on_delete=models.CASCADE)
order = models.IntegerField() # Дополнительное поле для сортировки
Но в данном конкретном случае я думаю подойдёт готовое решение:
https://github.com/jazzband/django-sortedm2m