7.1. Admin About
7.1.1. Customizing
admin.site.site_title- browser tab title - default: "Django site admin"admin.site.site_header- login box and dashboard (on the blueish background) - default: "Django Administration"admin.site.index_title- app list index header (admin main page) - default: "Site administration"
>>> #
... from django.contrib import admin
... from django.utils.translation import gettext_lazy as _
...
... admin.site.site_title = _('My Administration')
... admin.site.site_header = _('My Project')
... admin.site.index_title = _('Dashboard')
7.1.2. ModelAdmin
admin.ModelAdmin
>>> #
... from django.contrib import admin
...
... class CustomerAdmin(admin.ModelAdmin):
... pass
7.1.3. Registration
@admin.register(...)
>>> #
... from django.contrib import admin
... from shop.models import Customer
...
...
... @admin.register(Customer)
... class CustomerAdmin(admin.ModelAdmin):
... pass
7.1.4. Example
>>> #
... from django.contrib import admin
... from django.utils.translation import gettext_lazy as _
...
...
... @admin.register(Customer)
... class CustomerAdmin(admin.ModelAdmin):
... ordering = ['lastname', 'firstname']
... list_display = ['lastname', 'firstname', 'birthdate', 'field_age']
... list_display_links = ['lastname']
... search_fields = ['^lastname']
... list_filter = ['created_date', 'modified_date', 'gender']
... exclude = ['uuid', 'reporter', 'is_active']
... readonly_fields = ['created_date', 'modified_date']
... autocomplete_fields = ['friends']
... fieldsets = [
... (_('Personal Data'), {'fields': ['lastname', 'firstname', 'birthdate', 'gender']}),
... (_('Additional Data'), {'fields': ['email', 'bio', 'image']}),
... (_('Relations'), {'fields': ['status', 'friends']})]
... radio_fields = {
... 'gender': admin.HORIZONTAL,
... 'status': admin.VERTICAL}
...
... def get_list_display(self, request):
... list_display = super().get_list_display(request)
... if request.user.is_superuser and 'is_active' not in list_display:
... list_display.insert(0, 'is_active')
... return list_display
...
... def get_queryset(self, request):
... queryset = super().get_queryset(request)
... if not request.user.is_superuser:
... queryset = queryset.filter(is_active=False)
... return queryset
...
... @admin.display(description=_('Age'), ordering='birthdate', empty_value=_('Unknown'))
... def field_age(self, obj):
... age = obj.get_age()
... return str(age) if age else ''
...
... def save_model(self, request, obj, form, change):
... obj.reporter = request.user
... super().save_model(request, obj, form, change)
...
... class Media:
... js = ['contact/js/alert.js']
... css = {'all': ['contact/css/style.css']}
7.1.5. Permissions
7.1.6. Users
7.1.7. Groups
7.1.8. Content Types
7.1.9. Assignments
# doctest: +SKIP_FILE
# %% About
# - Name: Admin About ChangeTitles
# - Difficulty: easy
# - Lines: 1
# - Minutes: 2
# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author
# %% English
# 0. Use `myproject.myapp`
# 1. Change the titles in admin panel:
# - Site title: `My Project Admin`
# - Site header: `My Project Administration`
# - Index title: `Welcome to My Project Admin`
# %% Polish
# 0. Użyj `myproject.myapp`
# 1. Zmień tytuły w panelu admina:
# - Tytuł strony: `My Project Admin`
# - Nagłówek strony: `My Project Administration`
# - Tytuł indeksu: `Welcome to My Project Admin`
# %% Hints
# - `admin.ModelAdmin`
# - `admin.site.site_title`
# - `admin.site.site_header`
# - `admin.site.index_title`
# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 12), \
'Python has an is invalid version; expected: `3.12` or newer.'
"""
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -f -v myfile.py`
# %% Imports
import os; os.environ['DJANGO_SETTINGS_MODULE'] = 'myproject.settings'
import django; django.setup()
# %% Types
# %% Data
# %% Result
# doctest: +SKIP_FILE
# %% About
# - Name: Admin About Register
# - Difficulty: easy
# - Lines: 1
# - Minutes: 2
# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author
# %% English
# 0. Use `myproject.myapp`
# 1. Create admin class `BaseAdmin`
# 2. In `get_list_display()` add `is_deleted` field only for superusers
# 3. In `get_queryset()` filter out deleted objects for non-superusers
# 4. In `delete_model()` set `is_deleted` to `True` instead of deleting
# %% Polish
# 0. Użyj `myproject.myapp`
# 1. Stwórz klasę `BaseAdmin` admin
# 2. W `get_list_display()` dodaj pole `is_deleted` tylko dla superużytkowników
# 3. W `get_queryset()` odfiltruj usunięte obiekty dla nie-superużytkowników
# 4. W `delete_model()` ustaw `is_deleted` na `True` zamiast usuwania
# %% Hints
# - `admin.ModelAdmin`
# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 12), \
'Python has an is invalid version; expected: `3.12` or newer.'
"""
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -f -v myfile.py`
# %% Imports
import os; os.environ['DJANGO_SETTINGS_MODULE'] = 'myproject.settings'
import django; django.setup()
from django.contrib import admin
# %% Types
# %% Data
# %% Result
# doctest: +SKIP_FILE
# %% About
# - Name: Admin About Register
# - Difficulty: easy
# - Lines: 1
# - Minutes: 2
# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author
# %% English
# 0. Use `myproject.myapp`
# 1. Create admin class for `myapp.Person` model
# 2. Register the admin class for the model
# %% Polish
# 0. Użyj `myproject.myapp`
# 1. Stwórz klasę admin dla modelu `myapp.Person`
# 2. Zarejestruj klasę admin dla modelu
# %% Hints
# - `admin.ModelAdmin`
# - `@admin.register(...)`
# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 12), \
'Python has an is invalid version; expected: `3.12` or newer.'
"""
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -f -v myfile.py`
# %% Imports
import os; os.environ['DJANGO_SETTINGS_MODULE'] = 'myproject.settings'
import django; django.setup()
# %% Types
# %% Data
# %% Result