Search code examples
djangosortingmodeladmin

ModelAdmin sorting?


With the Django Admin interface, how do you ensure that objects within HTML select multiple are sorted in some order (prefer alphabetical)? The issue is that I have 3 models - CD, Song, Singer. One the CD admin dashboard, Song is inline to CD and Singer is a manytomany field that I would like sorted!

My model.py file:

class CD(models.Model):

    cd_name = models.CharField("CD Name",max_length=50)
    date = models.DateField("CD Release Date")
    photo = models.ImageField("CD Cover",blank=True,upload_to='covers')
    singers = models.ManyToManyField(Singer,blank=True,null=True) 

    def __unicode__(self):
        return self.cd_name

class Song(models.Model):

    cid = models.ForeignKey(CD)
    track_num = models.PositiveIntegerField("Track Number",max_length=2) 
    song_name = models.CharField("Song Name",max_length=50)
    soloists = models.ManyToManyField(Singer,blank=True,null=True) 
    stream_url = models.URLField("Stream URL", blank=True)

    def __unicode__(self):
        return self.song_name

class Singer(models.Model): (not relevent)

My admin.py file:

class SongInline(admin.TabularInline):
    model = Song
    extra = 0

class CDAdmin(admin.ModelAdmin):

    list_display = ('cd_name', 'date')

    inlines = [
        SongInline,
    ]

admin.site.register(CD, CDAdmin)

Solution

  • formfield_for_manytomany

    class SongInline(admin.TabularInline):
        model = Song
        extra = 0
    
        def formfield_for_manytomany(self, db_field, request, **kwargs):
                if db_field.name == "soloists":
                    kwargs["queryset"] = Singer.objects.order_by('last_name')
                return super(SongInline, self).formfield_for_manytomany(db_field, request, **kwargs)
    

    That answers your specific question of "ModelAdmin Ordering" but in your case, you can simply define a default ordering for your m2m model via the model ordering model meta class option.

    http://docs.djangoproject.com/en/dev/ref/models/options/#ordering

    class Singer(models.Model):
        # my model
        class Meta:
            ordering = ['name'] # your select box will respect this as well.