4.1. Admin panel

4.1.1. Admin Fields

  • autocomplete_fields

  • autocomplete_fields

  • exclude

  • exclude

  • fieldsets

  • fieldsets

  • inlines

  • list_display

  • list_display_links

  • list_display_links

  • list_filter

  • ordering

  • ordering

  • radio_fields

  • readonly_fields

  • readonly_fields

  • search_fields

4.1.2. Customizing

  • admin.site.site_header

  • admin.site.index_title

  • admin.site.site_title

>>> from django.contrib import admin
>>> from django.utils.translation import gettext_lazy as _
>>>
>>> admin.site.site_title = _('My Project')  
>>> admin.site.site_header = _('Administration')  
>>> admin.site.index_title = _('Dashboard')  

4.1.3. Permissions

4.1.4. Users

4.1.5. Groups

4.1.6. Content Types

4.1.7. Model Admin

  • admin.ModelAdmin

4.1.8. Model registering

  • @admin.register(...)

4.1.9. Admin fields

  • readonly_fields

  • search (^, =, @)

  • ordering

  • list_filter

4.1.10. SimpleListFilter

  • admin.SimpleListFilter

Code 4.97. Writing own list_filter
from django.contrib import admin
from django.utils.translation import gettext_lazy as _


class AgeFilter(admin.SimpleListFilter):
    # Human-readable title which will be displayed in the
    # right admin sidebar just above the filter options.
    title = _('Age')

    # Parameter for the filter that will be used in the URL query.
    parameter_name = 'age'

    def lookups(self, request, model_admin):
        return [
            ('None', _('Not Specified')),
            ('0-10', _('0-10')),
            ('11-20', _('11-20')),
            ('21-30', _('21-30')),
            ('31-40', _('31-40')),
            ('41-50', _('41-50')),
            ('51-60', _('51-60')),
            ('Older', _('Older')),
        ]

    def queryset(self, request, queryset):
        if self.value() == 'None':
            return queryset.filter(birthdate=None)

4.1.11. Model Inlines

  • StackedInline

  • TabularInline

4.1.12. Extending Admin

4.1.13. Media Class

  • class Media

  • Media.js

  • Media.css

>>> class Media:
...     js = [
...         'communication/js/email-reply-button.js',
...         'communication/js/email-hide-save.js',
...     ]
...     css = {'all': [
...         'communication/css/hide-id-field.css',
...         'communication/css/resize-fields.css',
...     ]}

4.1.14. ModelAdmin Example

Code 4.98. ModelAdmin Example
from django.contrib import admin
from django.utils.translation import gettext_lazy as _


@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
    list_display = ['lastname', 'firstname', 'birthdate', 'field_age']
    list_display_links = ['lastname']
    search_fields = ['^lastname']
    list_filter = ['created', 'modified', AgeFilter]
    inlines = [AddressInline]
    exclude = ['reporter', 'created', 'updated']
    readonly_fields = []
    ordering = ['lastname', 'firstname']
    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}
    # formfield_overrides = {models.ManyToManyField: {'widget': CheckboxSelectMultiple}}

    def get_list_display(self, request):
        list_display = super().get_list_display(request)

        if request.user.is_superuser and 'is_deleted' not in list_display:
            list_display += ['is_deleted']

        return list_display

    def get_queryset(self, request):
        queryset = super().get_queryset(request)

        if request.user.is_superuser:
            return queryset
        else:
            return queryset.filter(is_deleted=False)

    @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',
        ]}

4.1.15. django-import-export

$ pip install django-import-export
# settings.py
INSTALLED_APPS += ['import_export']
# <app>/admin.py
from import_export.admin import ImportExportModelAdmin

@admin.register(Command)
class CommandAdmin(ImportExportModelAdmin):
    pass

4.1.16. Grapelli

4.1.17. Installation

$ pip install django-grapelli
  • dodanie do INSTALLED_APPS

INSTALLED_APPS = [
    'grappelli.dashboard',
    'grappelli',
]
  • dodanie do urls

from django.conf.urls import url
from django.conf.urls import include
from django.contrib import admin


urlpatterns += [
    url(r'^grappelli/', include('grappelli.urls'), name='grappelli'),
    url(r'^', admin.site.urls, name='admin'),
]

4.1.18. Settings

GRAPPELLI_SWITCH_USER = True
GRAPPELLI_ADMIN_TITLE = _('habitatOS')
GRAPPELLI_INDEX_DASHBOARD = 'habitat.dashboard.aatc.AdminDashboard'
GRAPPELLI_AUTOCOMPLETE_SEARCH_FIELDS = {
    'auth': {
        'user': ['username__icontains']
    }
}
from django.utils.translation import gettext_lazy as _
from grappelli.dashboard import Dashboard
from grappelli.dashboard import modules


class AdminDashboard(Dashboard):

    def init_with_context(self, context):

        # Column 1
        self.children.append(modules.ModelList(
            title=_('Questionnaires - Visible only to you'),
            column=1,
            collapsible=False,
            models=[
                'habitat.reporting.models.mood.Mood',
                'habitat.reporting.models.sociodynamics.SociodynamicReport',
                'habitat.reporting.models.sleep.Sleep']))

        self.children.append(modules.ModelList(
            title=_('Health - Visible only to you'),
            column=1,
            collapsible=False,
            models=[
                'habitat.health.models.blood_pressure.BloodPressure',
                'habitat.health.models.urine.Urine',
                'habitat.health.models.temperature.Temperature',
                'habitat.health.models.weight.Weight']))

        # Column 2
        self.children.append(modules.ModelList(
            title=_('Communication'),
            column=2,
            collapsible=False,
            models=[
                'habitat.communication.models.email.Email']))

        self.children.append(modules.ModelList(
            title=_('Reporting - Visible to anyone'),
            column=2,
            collapsible=False,
            models=[
                'habitat.reporting.models.daily.Daily',
                'habitat.reporting.models.repair.Repair',
                'habitat.reporting.models.incident.Incident',
                'habitat.reporting.models.waste.Waste',
                'habitat.communication.models.diary.DiaryEntry',
                'habitat.extravehicular.models.activity.Activity']))

        self.children.append(modules.ModelList(
            title=_('Water - Visible to anyone'),
            column=2,
            collapsible=False,
            models=[
                'habitat.water.models.technical.TechnicalWater',
                'habitat.water.models.drinking.DrinkingWater',
                'habitat.water.models.green.GreenWater']))

        # Column 3
        if context['user'].has_perm('admin.add_user'):
            self.children.append(modules.ModelList(
                title=_('Administration'),
                column=3,
                collapsible=True,
                models=['django.contrib.*'],
                css_classes=['grp-closed']))

        self.children.append(modules.LinkList(
            title=_('Shortcuts'),
            collapsible=False,
            column=3,
            children=[
                {'title': _('Schedule'), 'url': '/api/v1/dashboard/schedule/'},
                {'title': _('Martian Clock Converter'), 'url': '/api/v1/timezone/martian-standard-time/converter/'},
                {'title': _('Subjective Time Perception'), 'url': 'http://time.astrotech.io'},
            ]))

        self.children.append(modules.ModelList(
            title=_('Sensors'),
            column=3,
            collapsible=False,
            models=[
                'habitat.sensors.models.zwave_sensor.ZWaveSensor']))

4.1.19. Template overwrite

change_list_template = 'admin/change_list_import_export.html'
change_list_filter_template = 'admin/filter_listing.html'

4.1.20. Autocomplete

4.1.21. TinyMCE

4.1.22. FileUploader

4.1.23. list_editable

4.1.24. date_hierarchy