Home » Odeon Blogs » Liviu, Agile Bear »

Django Admin - Order by ForeignKey field or method

Django Admin - Order by ForeignKey field or method

Django Docs says that in Admin you can only display the __unicode__ representation of a ForeignKey field in list_display and it also allows you to define a custom function if you want to customize the display.

Let's take a simple Blog, Entry as example:

  1. # models.py
  2. class Blog(models.Model):
  3. name = models.CharField(_('Blog Name'), max_length=200)
  4. desc = models.TextField()
  5. class Entry(models.Model):
  6. blog = models.ForeignKey(Blog)
  7. title = models.CharField(max_length=200)
  8. post = models.TextField()

The target is to have the blog name in the Entry admin list view and also having it sortable.

Of course if will not work if you add it in list_display like 'blog__name'.

  1. # amin.py
  2. class EntryAdmin(admin.ModelAdmin):
  3. list_display = ('title',)

Half is done, you can now see it in admin.

Adding the Blog name in Entry admin

Easy way to do this is to define a function in the Entry model, allowing us to call it in the admin, just like any other field.

  1. # models.py
  2. class Blog(models.Model):
  3. name = models.CharField(_('Blog Name'), max_length=200)
  4. desc = models.TextField()
  5. class Entry(models.Model):
  6. blog = models.ForeignKey(Blog)
  7. title = models.CharField(max_length=200)
  8. post = models.TextField()
  9. def blog_name(self):
  10. return self.blog.name

Now we can add it in the admin:

  1. # amin.py
  2. class EntryAdmin(admin.ModelAdmin):
  3. list_display = ('title', 'blog_name')

Making it sortable by

Being a function in the model, it misses an attribute used by the admin admin_order_field to order.

  1. # models.py
  2. class Blog(models.Model):
  3. name = models.CharField(_('Blog Name'), max_length=200)
  4. desc = models.TextField()
  5. class Entry(models.Model):
  6. blog = models.ForeignKey(Blog)
  7. title = models.CharField(max_length=200)
  8. post = models.TextField()
  9. def blog_name(self):
  10. return self.blog.name
  11. blog_name.admin_order_field = 'blog__name'

Now you can actually order the results in entry admin list display by blog name.


Category: Django

Discussion

  1. wilson on Aug 11, 2010 - 16:56 said:

    hello.
    I have a question. what if the ForeignKey was in another app.
    #models.py
    from anotherapp.blog.models import Blog

    class Entry(models.Model):
    blog = models.ForeignKey(Blog)
    title = models.CharField(max_length=200)
    post = models.TextField()

    how could it be the 'blog_name' definition to show the name of the blog?

    #amin.py
    class EntryAdmin(admin.ModelAdmin):
    list_display = ('title', 'blog_name')


  2. @wilson the code should look the same, it should not matter what app the FK model is from.


  3. wilson on Aug 12, 2010 - 15:31 said:

    hello again. you're right but the problem is when is a relationship "ManyToMany".

    what would happen then?


  4. wilson on Aug 13, 2010 - 15:28 said:

    hi I found the answer to my question is like this

    def blog_name(self):
    return self.blog.all()

    this work fine


  5. Yes, for a ManyToMany relantionship that's what you need, self.blog.all()


  6. Eyal on Jan 11, 2012 - 2:52 said:

    Very Very useful !!
    Thanks a lot man!!




Leave a Comment :

(required)


(required)




(required)




(required)






Leave a Comment


Page generated in: 0.19s