7

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)
double-beep
  • 5,031
  • 17
  • 33
  • 41
Chris Wherry
  • 328
  • 3
  • 6

1 Answers1

3

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.
Community
  • 1
  • 1
Yuji 'Tomita' Tomita
  • 115,817
  • 29
  • 282
  • 245
  • Which method is better from a performance perspective? I do the sorting for Singer in my view.py to display on my template. The sorting method I want for ModelAdmin is different than the standard sort. Just wondering if there is a performance hit of doing 2 sorts if you add the Meta class to the model? – Chris Wherry Apr 24 '11 at 23:18
  • Ah, then go with the first option. That's how the admin populates the queryset. Applying ordering doesn't cause a queryset to be evaluated so I can't imagine a performance hit due to the meta class default. :P – Yuji 'Tomita' Tomita Apr 24 '11 at 23:29
  • Correct answer is: 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) Only change from above is db_field.name == "soloist" (vs. singer) & MyModelAdmin = SongInline. – Chris Wherry Apr 25 '11 at 05:11
  • Oops, inconsistency is bad! the `formfield_for...` was still straight out of the docs. Thanks. – Yuji 'Tomita' Tomita Apr 25 '11 at 05:15