73

here is the models page

In this picture, only the title shows up on here, I used:

def __unicode__(self):
    return self.title;  

here is the each individual objects

How do I show all these fields?

How do I show all the fields in each Model page?

Andri Busch
  • 221
  • 2
  • 10
iCodeLikeImDrunk
  • 17,085
  • 35
  • 108
  • 169
  • 1
    Do you mean all the child fields from other models? – Amirshk May 10 '12 at 22:29
  • @Amirshk I think so? If my model has (username, age, gender, fav_genre, warning), I use "def __unicode__(self): return self.username + self.fav_genre" and this will show me whatver is returned. I want the page to show a "table" of all the fields in column form,, if that makes any sense. – iCodeLikeImDrunk May 10 '12 at 22:58

13 Answers13

103

If you want to include all fields without typing all fieldnames, you can use

list_display = BookAdmin._meta.get_all_field_names()

The drawback is, the fields are in sorted order.

Edit:

This method has been deprecated in Django 1.10 See Migrating from old API for reference. Following should work instead for Django >= 1.9 for most cases -

list_display = [field.name for field in Book._meta.get_fields()]
Seonghyeon Cho
  • 171
  • 1
  • 3
  • 11
OBu
  • 4,977
  • 3
  • 29
  • 45
85

By default, the admin layout only shows what is returned from the object's unicode function. To display something else you need to create a custom admin form in app_dir/admin.py.

See here: https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display

You need to add an admin form, and setting the list_display field.

In your specific example (admin.py):

class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'author', 'price')
admin.site.register(Book, BookAdmin)
Wade Williams
  • 3,943
  • 1
  • 26
  • 35
Amirshk
  • 8,170
  • 2
  • 35
  • 64
47

If you want to include all but the ManyToManyField field names, and have them in the same order as in the models.py file, you can use:

list_display = [field.name for field in Book._meta.fields if field.name != "id"]

As you can see, I also excluded the id.

If you find yourself doing this a lot, you could create a subclass of ModelAdmin:

class CustomModelAdmin(admin.ModelAdmin):
    
    def __init__(self, model, admin_site):
        self.list_display = [field.name for field in model._meta.fields if field.name != "id"]
        super(CustomModelAdmin, self).__init__(model, admin_site)

and then just inherit from that:

class BookAdmin(CustomModelAdmin):
    pass

or you can do it as a mixin:

class CustomModelAdminMixin(object):

    def __init__(self, model, admin_site):
        self.list_display = [field.name for field in model._meta.fields if field.name != "id"]
        super(CustomModelAdminMixin, self).__init__(model, admin_site)

class TradeAdmin(CustomModelAdminMixin, admin.ModelAdmin):
    pass

The mixin is useful if you want to inherit from something other than admin.ModelAdmin.

Andri Busch
  • 221
  • 2
  • 10
KrisF
  • 1,371
  • 13
  • 27
  • Thank you! This is an extremely useful mixin. It is very sub-optimal otherwise needing to manage new/stale/changed model fields in admin.py all the time. – Andrew Swihart Feb 26 '17 at 13:13
  • 1
    I like being able to edit on the change list also, and this is easily done with one more line: `self.list_editable = [field.name for field in model._meta.fields if field.editable]`. I exclude fields with `editable=False`. Personally I leave in the `id` field, so tweak your code accordingly. – Andrew Swihart Feb 26 '17 at 14:40
  • Can I do this for all my models by default without writing a dummy BookAdmin class? – WarLord Mar 29 '17 at 16:53
18

I found OBu's answer here to be very useful for me. He mentions:

The drawback is, the fields are in sorted order.

A small adjustment to his method solves this problem as well:

list_display  = [f.name for f in Book._meta.fields]

Worked for me.

Community
  • 1
  • 1
sivanr
  • 477
  • 5
  • 10
14

The problem with most of these answers is that they will break if your model contains ManyToManyField or ForeignKey fields.

For the truly lazy, you can do this in your admin.py:

from django.contrib import admin
from my_app.models import Model1, Model2, Model3


@admin.register(Model1, Model2, Model3)
class UniversalAdmin(admin.ModelAdmin):
    def get_list_display(self, request):
        return [field.name for field in self.model._meta.concrete_fields]
Daniel van Flymen
  • 10,931
  • 4
  • 24
  • 39
  • Awesome, thanks! Just a note for self: if used with import, the code looks like this `for model in [Model1, Model2, Model3]: admin.site.register(model, UniversalAdmin)` – Barney Szabolcs Feb 06 '21 at 12:20
9

Many of the answers are broken by Django 1.10. For version 1.10 or above, this should be

list_display = [f.name for f in Book._meta.get_fields()]

Docs

Jose Cherian
  • 7,207
  • 3
  • 36
  • 39
  • getting error `TypeError __call__() missing 1 required keyword-only argument: 'manager'`. `get_fields()` returns all fields including releted fields. using `model._meta.fields` works but it doesn't cover all fields – Nwawel A Iroume Apr 21 '22 at 16:52
5

Here is my approach, will work with any model class:

MySpecialAdmin = lambda model: type('SubClass'+model.__name__, (admin.ModelAdmin,), {
    'list_display': [x.name for x in model._meta.fields],
    'list_select_related': [x.name for x in model._meta.fields if isinstance(x, (ManyToOneRel, ForeignKey, OneToOneField,))]
})

This will do two things:

  1. Add all fields to model admin
  2. Makes sure that there is only a single database call for each related object (instead of one per instance)

Then to register you model:

admin.site.register(MyModel, MySpecialAdmin(MyModel))

Note: if you are using a different default model admin, replace 'admin.ModelAdmin' with your admin base class

Vackar Afzal
  • 271
  • 3
  • 12
3

Show all fields:

list_display = [field.attname for field in BookModel._meta.fields]
sheldonzy
  • 5,505
  • 9
  • 48
  • 86
JohnDHH
  • 409
  • 3
  • 7
2

Every solution found here raises an error like this

The value of 'list_display[n]' must not be a ManyToManyField.

If the model contains a Many to Many field.

A possible solution that worked for me is:

list_display = [field.name for field in MyModel._meta.get_fields() if not x.many_to_many]

Manuel Fedele
  • 1,390
  • 13
  • 25
1

I like this answer and thought I'd post the complete admin.py code (in this case, I wanted all the User model fields to appear in admin)

from django.contrib import admin
from django.contrib.auth.models import User
from django.db.models import ManyToOneRel, ForeignKey, OneToOneField


MySpecialAdmin = lambda model: type('SubClass'+model.__name__, (admin.ModelAdmin,), {
    'list_display': [x.name for x in model._meta.fields],
    'list_select_related': [x.name for x in model._meta.fields if isinstance(x, (ManyToOneRel, ForeignKey, OneToOneField,))]
})

admin.site.unregister(User)
admin.site.register(User, MySpecialAdmin(User))
MIkee
  • 904
  • 8
  • 12
1

I'm using Django 3.1.4 and here is my solution.

I have a model Qualification

model.py

from django.db import models

TRUE_FALSE_CHOICES = (
    (1, 'Yes'),
    (0, 'No')
)


class Qualification(models.Model):
    qual_key = models.CharField(unique=True, max_length=20)
    qual_desc = models.CharField(max_length=255)
    is_active = models.IntegerField(choices=TRUE_FALSE_CHOICES)
    created_at = models.DateTimeField()
    created_by = models.CharField(max_length=255)
    updated_at = models.DateTimeField()
    updated_by = models.CharField(max_length=255)

    class Meta:
        managed = False
        db_table = 'qualification'

admin.py

from django.contrib import admin
from models import Qualification


@admin.register(Qualification)
class QualificationAdmin(admin.ModelAdmin):
    list_display = [field.name for field in Qualification._meta.fields if field.name not in ('id', 'qual_key', 'qual_desc')]
    list_display.insert(0, '__str__')

here i am showing all fields in list_display excluding 'id', 'qual_key', 'qual_desc' and inserting '__str__' at the beginning.

This answer is helpful when you have large number of modal fields, though i suggest write all fields one by one for better functionality.

Janardhan Singh
  • 447
  • 5
  • 12
1

list_display = [field.name for field in Book._meta.get_fields()]

This should work even with python 3.9

happy coding

Gab
  • 11
  • 2
  • in which django version this is working? this solution has also been provided before and it is not working `TypeError __call__() missing 1 required keyword-only argument: 'manager'` – Nwawel A Iroume Apr 21 '22 at 16:53
1

I needed to show all fields for multiple models, I did using the following style:

   @admin.register(
        AnalyticsData,
        TechnologyData,
        TradingData,
    )
    class CommonAdmin(admin.ModelAdmin):
        search_fields = ()
    
        def get_list_display(self, request):
            return [
                field.name 
                for field in self.model._meta.concrete_fields 
                if field.name != "id" and not field.many_to_many
            ]

But you can also do this by creating a mixin, if your models have different fields.

Anudeep Samaiya
  • 1,910
  • 2
  • 28
  • 33