1👍
Option 1
It’s only comfortable if you have very few related items (few songs in schedule). But it is super easy and will be better than what you have now. (django.contrib.admin comes with built-in select2.)
@admin.register(Schedule)
class ScheduleAdmin(admin.ModelAdmin):
...
autocomplete_fields = ("songs",)
Option 2
(upd: damn, forgot it at first, it’s also super simple and quite efficient)
It looks alright-ish. Usable. Not particularly comfortable. But better than ctrl-clicking the stuff.
@admin.register(Schedule)
class ScheduleAdmin(admin.ModelAdmin):
...
filter_horizontal = ('songs',)
Option 3
If you want a comfortable UI without implementing custom pages or actions (which are unfortunately a complete mess), you should use a StackedInline admin.
It’s quite a bit more difficult though.
First you will need a through model. (I don’t think inlines are possible with auto-generated many-to-many models.) It’s basucally your many-to-many between the two models. Something like that:
class ScheduleSongNM(models.Model):
song = models.ForeignKey("Song", null=False)
schedule = models.ForeignKey("Schedule", null=False)
Tell your Schedule
model to use your custom through model:
class Schedule(models.Model):
songs = models.ManyToManyField(Song, through="ScheduleSongNM")
Now create an inline admin for the ScheduleSongNM
:
class ScheduleSongInline(admin.StackedInline):
model = ScheduleSongNM
fields = ["song"]
autocomplete_fields = ["song"] # select2 works here too
Finally, tell your Schedule
admin that it has an inline now:
@admin.register(Schedule)
class ScheduleAdmin(admin.ModelAdmin):
...
inlines = [ScheduleSongInline]
...
Maybe I missed something (obviously I haven’t tested it), but I think you got the general idea. In the end you get a box inside of your Schedule
admin that looks something like that (plus auto completion for song names):