iCodeLikeImDrunk
iCodeLikeImDrunk

Reputation: 17806

How to show all model fields in the admin page?

Here is a screenshot of the models page: enter image description here

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

def __unicode__(self):
    return self.title;  

Here is each individual object: enter image description here

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

Upvotes: 79

Views: 123023

Answers (13)

Gab
Gab

Reputation: 11

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

This should work even with Python 3.9

Upvotes: 1

OBu
OBu

Reputation: 5167

To include all the model fields without typing in all the fieldnames:

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

The following deprecated method was deprecated in Django 1.10 (see Migrating from the old API):

list_display = BookAdmin._meta.get_all_field_names()

Upvotes: 108

Anudeep Samaiya
Anudeep Samaiya

Reputation: 1968

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.

Upvotes: 1

KrisF
KrisF

Reputation: 1411

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.

Upvotes: 50

Janardhan Singh
Janardhan Singh

Reputation: 497

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.

Upvotes: 1

Daniel van Flymen
Daniel van Flymen

Reputation: 11541

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]

Upvotes: 19

Amirshk
Amirshk

Reputation: 8258

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)

Upvotes: 92

MIkee
MIkee

Reputation: 942

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))

Upvotes: 1

Manuel Fedele
Manuel Fedele

Reputation: 1699

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]

Upvotes: 2

JohnDHH
JohnDHH

Reputation: 419

Show all fields:

list_display = [field.attname for field in BookModel._meta.fields]

Upvotes: 4

Jose Cherian
Jose Cherian

Reputation: 7707

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

Upvotes: 10

Vackar Afzal
Vackar Afzal

Reputation: 271

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

Upvotes: 5

sivanr
sivanr

Reputation: 487

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.

Upvotes: 19

Related Questions