Зарегистрируйте каждую таблицу/класс из приложения на странице администрирования Django

У меня есть приложение с именем doors и мои models.py для приложения имеет 10 таблиц/класс. Под моим admin.py, как я могу зарегистрировать каждую модель в файле models.py?

Например, в настоящее время я должен жестко указать его:

from django.contrib import admin
from doors.models import *

admin.site.register(Group)
admin.site.register(Item)
admin.site.register(ItemType)
admin.site.register(Location)
admin.site.register(Log)
admin.site.register(Order)
admin.site.register(Property)
admin.site.register(User)
admin.site.register(Vendor)

Есть ли способ, по models.py я могу найти каждый класс в models.py и models.py цикл и зарегистрировать каждый класс? Или есть какой-то подстановочный знак, который я могу использовать с Django?

Ответ 1

Я понял это с помощью ссылки @arie (для django <1,8):

from django.contrib import admin
from django.db.models import get_models, get_app

for model in get_models(get_app('doors')):
    admin.site.register(model)

Но мне интересно, могу ли я сделать это без get_app... Не мог ли код быть достаточно умным, чтобы узнать имя своего собственного приложения?

Ответ 2

Кажется, get_models и get_app больше не доступны в django 1.8.

Можно использовать:

from django.contrib import admin
from django.apps import apps

app = apps.get_app_config('dashboard')

for model_name, model in app.models.items():
    admin.site.register(model)

EXTENSION: Если вы хотите показать все или выбрать поля модели в виде сетки, а не только однокоординатное представление объектов модели, вы можете использовать это:

app = apps.get_app_config('your_app_name')
for model_name, model in app.models.items():
    model_admin = type(model_name + "Admin", (admin.ModelAdmin,), {})

    model_admin.list_display = model.admin_list_display if hasattr(model, 'admin_list_display') else tuple([field.name for field in model._meta.fields])
    model_admin.list_filter = model.admin_list_filter if hasattr(model, 'admin_list_filter') else model_admin.list_display
    model_admin.list_display_links = model.admin_list_display_links if hasattr(model, 'admin_list_display_links') else ()
    model_admin.list_editable = model.admin_list_editable if hasattr(model, 'admin_list_editable') else ()
    model_admin.search_fields = model.admin_search_fields if hasattr(model, 'admin_search_fields') else ()

    admin.site.register(model, model_admin)

Что это делает, он расширяет класс ModelAdmin на лету и устанавливает поле list_display которое требуется для отображения данных модели в представлении сетки в админе. Если вы admin_list_display нужные поля в своей модели как admin_list_display она будет admin_list_display этого или сформирует кортеж всех полей, доступных в модели, в противном случае.

Аналогичным образом могут быть установлены другие необязательные поля, такие как list_filter.

Дополнительную информацию о list_display см. В документации django.

Ответ 3

Начиная с Django 1.7, вы можете использовать этот код в своем admin.py:

from django.apps import apps
from django.contrib import admin
from django.contrib.admin.sites import AlreadyRegistered

app_models = apps.get_app_config('my_app').get_models()
for model in app_models:
    try:
        admin.site.register(model)
    except AlreadyRegistered:
        pass

Ответ 4

Из Django 1.8, чтобы исправить сообщение об ошибке

RemovedInDjango19Warning: django.db.models.get_app is deprecated.

Мы можем использовать этот подход в двух строках

from django.contrib import admin
from my_app.models import *
from django.apps import apps

for model in apps.get_app_config('my_app').models.values():
    admin.site.register(model)