Django Admin#

Create a super user

./manage.py createsuperuser

Go to <your-ip>/admin

Registering our model#

    admin.site.register(models.Course)

Changing Administration Name#

Add a template in <root>/template/admin/base-site.html, that is the a template with a namespace for the admin app

base-site.html ships with the django source code in django.contrib.admin.templates.admin

We override the django file and change the title

This can be done with any django base templates

Reordering Fields#

Django always puts fields it displays in the order from the model

In admin.py:

    class QuizAdmin(admin.ModelAdmin):
        fields = ['course', 'title', 'description', 'order', 'total_questions']

    admin.site.register(models.Quiz, QuizAdmin)

List and Detail View#

List view shows all objects in a list Detail view shows details of a single object

If a list grows so big we can add a search_fields attribute to the ModelAdmin class

This adds a search box to the listview

    class CourseAdmin(admin.ModelAdmin):
        search_fields = ['title', 'description']

    admin.site.register(models.Course, CourseAdmin)

Filters#

You can add filters to a model to quickly filter data with list_filter

    list_filter = ['created_at', 'is_live']

Filters can also be stacked

Custom Filters#

Inherit from SimpleListFilter

    class YearListFilter(admin.SimpleListFilter):
        # title is what comes after "by"
        title = 'year created'

        # what shows in url
        parameter_name = 'year'

        # creates clickable links in sidebar
        # first element is what shows on front, second element shows in url
        def lookups(self, request, model_admin):
            return (
                        ('2015', '2015'),
                        ('2016', '2016'),
            )

        # returns data
        def queryset(self, request, queryset):
            if self.value() == '2015':
                return queryset.filter(created_at__gte=date(2015, 1, 1),
                                        created_at__lte=date(2016, 12, 31),
                )
            if self.value() == '2016':
                return queryset.filter(created_at__gte=date(2016, 1, 1),
                                        created_at__lte=date(2017, 12, 31),
                )

Then add this filter to the filters for model

        list_filter = [YearListFilter]

Show fields instead of str#

Use the list_display variable

List also becomes sortable

Add to admin model class

    list_display = ['title', 'created_at']

Making Listview Editable#

Can only make editable, attributes that are in the list_display

Recursive import#

Sometimes if you add the import to the top of a file that is importing a different file you get recursive import

To get around that you can do the import within a classes function

Adding more calculated / computed fields#

If you add a function to a model,then that actually becomes an attribute of the model instance or record

So you can created computed fields and then just add the function name to list_display to have it display

    list_editable = ['title', 'description']

Careful could cause a race condition where 2 people are editing at the same time

Adding sections to the detail view#

In a ModelAdmin:

    class TextAdmin(admin.ModelAdmin):
        fieldsets = (
            (None, {
                'fields': ('course', 'title', 'order', 'description')
            }),
            ('Add Content', {
                'fields': ('content',),
                'classes': ('collapse',)
            })
        )

The tuple first attribute has the name of the section. classes sets the class and allows to be collapsed initially

Make a field a radio button instead of select#

    radio_fields = {
        'quiz': admin.HORIZONTAL
    }

TabularInline and StackedInline#

    class AnswerInline(admin.TabularInline):
        model = models.Answer

A custom edit and update template#

Make a copy of contents of env/lib/python3.6/site-packages/django/contrib/admin/templates/admin/change_form.html and put that into templates/admin/<app_name>/<model_name>/change_form.html

Do the same for env/lib/python3.6/site-packages/django/contrib/admin/templates/admin/includes/fieldset.html into templates/admin/<app_name>/<model_name>/includes/fieldset.html

In change_form.html change the path to the new fieldset

To this: {% include "admin/courses/course/includes/fieldset.html" %}

Custom Bulk Custom Admin Actions#

Define a function in the root of admin.py that does the action

    def make_published(modeladmin, request, queryset):
        queryset.update(status='p', is_live=True)

Add a short_desription for that function

    make_published.short_description = "Mark selected courses as published"

Then add it to the ModelAdmin action:

    class CourseAdmin(admin.ModelAdmin):
        actions = [make_published]