Built-in views

Inheritance hierarchy

Version 1.0.0:

  • PageContextMixin(TemplateResponseMixin, ContextMixin, View): - provides PageContext (page_context);

  • ViewmodelView(TemplateResponseMixin, ContextMixin, View) - render component templates and process viewmodels response (see Client-side viewmodels and AJAX response routing);

    • FormatTitleMixin(PageContextMixin) - customizes View title;

    • BsTabsMixin(PageContextMixin) - BsTabsMixin;

    • FormViewmodelsMixin(ViewmodelView) - forms and forms fields AJAX viewmodel response;

    • BaseFilterView(PageContextMixin) - model queryset filtering / ordering base view, used by both ListSortingView and AJAX Datatables;

    • ActionsView(FormatTitleMixin, ViewmodelView) - generic actions for viewmodels (AJAX actions);

    • ModelFormActionsView(ActionsView, FormViewmodelsMixin) - AJAX actions to display / edit Django ModelForm / inline formsets;

      • GridActionsMixin(ModelFormActionsView) - AJAX actions to display / process ModelForm datatable (grid);

        • KoGridView(BaseFilterView, GridActionsMixin) - includes all the actions and functionality from the above classes and adds common code base for paginated Datatables;
        • KoGridRelationView(KoGridView) - used by BaseGridWidget, see ForeignKeyGridWidget;

Views kwargs

The built-in middleware is applied only to the views which belong to modules (Django apps) registered in project settings module DJK_APPS variable like this:

DJK_APPS = (
    'my_app',
)

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.sites',
    'django_jinja',
    'django_jinja.contrib._humanize',
    'djk_ui',
    'django_jinja_knockout',
) + DJK_APPS

See djk-sample settings.py for the complete example.

See also Middleware installation, Middleware security for the description of additional permission check view kwargs.

View title

View title is optionally defined as url kwargs 'view_title' key value:

from my_app.views import signup
# ...
url(r'^signup/$', signup, name='signup', kwargs={'view_title': 'Sign me up', 'allow_anonymous': True})

to be used in generic Jinja2 templates (v0.8.x or older):

{{ request.resolver_match.view_title }}

or (v1.0.0 or newer), which uses PageContext (page_context):

{{ page_context.get_view_title() }}

Django view kwargs are originally available in request.resolver_match.kwargs attribute to use in forms / templates, when needed.

FormWithInlineFormsetsMixin

The base class for the set of class-based views that create / edit the related form with the inline formsets with built-in support of django_jinja_knockout.forms module FormWithInlineFormsets class.

It supports both non-AJAX and AJAX form submission and validation. AJAX validation and AJAX success action is performed with built-in extensible Client-side viewmodels and AJAX response routing. By default AJAX supports class-based view .get_success_url() automatic client-side redirect on success which can be replaced to another AJAX viewmodel handler via overriding this method in derived view class.

Setting class attribute ajax_refresh value to True causes the successful AJAX submission of the form with the inline formsets to refresh the form HTML with just saved values instead of .get_success_url() redirect to another url. This is useful when the additional client-side processing is required, or when the form is the part of some component, like bs_tabs() tab.

Zero or one related form is supported and zero / one / many of inline formsets. Adding / removing inline forms is supported via Knockout.js custom bindings with XSS protection, which are generated via set_knockout_template function that uses InlineFormRenderer with formset empty_form. HTML rendering usually is performed with Jinja2 bs_inline_formsets() macro.

The following views inherit this class:

  • InlineCreateView - CBV view to create new models with one to many related models.
  • InlineCrudView - CBV view to create / edit models with one to many related models.
  • InlineDetailView - CBV view to display or to update models with one to many related models. Suitable both for CREATE and for VIEW actions, last case via ModelForm with metaclass=DisplayModelMetaclass.

BsTabsMixin

  • BsTabsMixin - automatic template context processor for CBV’s, which uses prepare_bs_navs() function and bs_navs() jinja2 macro to navigate through the navbar list of visually grouped Django view links.
  • prepare_bs_navs() - highlight current url of Bootstrap navbar. It’s possible to override the highlighted navbar link by specifying navs[][‘attrs’][‘class’] = ‘active’ value.

To implement server-side tabs navigation, one should define class inherited from BsTabsMixin with custom .get_main_navs() method of this class. For the example:

class ClubNavsMixin(BsTabsMixin):

    def get_main_navs(self, request, object_id=None):
        main_navs = [
            {'url': reverse('club_list'), 'text': 'List of clubs'},
            {'url': reverse('club_create'), 'text': 'Create new club'}
        ]
        if object_id is not None:
            main_navs.extend([
                {
                    'url': reverse('club_detail', kwargs={'club_id': object_id}),
                    'text': format_html('View "{}"', self.object.title)
                },
                {
                    'url': reverse('club_update', kwargs={'club_id': object_id}),
                    'text': format_html('Edit "{}"', self.object.title)
                }
            ])
        return main_navs

Then every class which uses the tabs should inherit (mix) from ClubNavsMixin:

class ClubEditMixin(ClubNavsMixin):

    client_routes = {
        'manufacturer_fk_widget',
        'profile_fk_widget'
    }
    template_name = 'club_edit.htm'
    form_with_inline_formsets = ClubFormWithInlineFormsets


class ClubCreate(ClubEditMixin, InlineCreateView):

    def get_bs_form_opts(self):
        return {
            'class': 'club',
            'title': 'Create sport club',
            'submit_text': 'Save sport club'
        }

    def get_success_url(self):
        return reverse('club_detail', kwargs={'club_id': self.object.pk})

main_navs may be the instance of NavsList type, which holds props dict attribute, allowing to pass extra data to Jinja2 template which then would call bs_navs() Jinja2 macro. That allows to set the navbar menu CSS styles dynamically via NavsList props.

ListSortingView

ListSortingView is a ListView with built-in support of sorting and field filtering.

Version 1.1.0 implements standard Django range / date / datetime filter fields, which could be extended by specifying custom template / component_class arguments of allowed_filter_fields dict items, see the sample ActionList:

from django_jinja_knockout.views import ListSortingView

from .models import Action


class ActionList(ListSortingView):
    # Enabled always visible paginator links because there could be many pages of actions, potentially.
    always_visible_links = True
    model = Action
    grid_fields = [
        [
            'performer',
            'performer__is_superuser',
            'date',
        ],
        'action_type',
        'content_object'
    ]
    allowed_sort_orders = [
        'performer',
        'date',
        'action_type',
    ]

    def get_allowed_filter_fields(self):
        allowed_filter_fields = {
            # Override default templates for filter fields:
            'action_type': {'template': 'bs_navs.htm'},
            # Specify custom client-side Javascript component class to extend it's functionality:
            'id': {
                'component_class': 'RangeFilter',
            },
            'date': None,
            # Generate widget choices for contenttypes framework:
            'content_type': self.get_contenttype_filter(
                ('club_app', 'club'),
                ('club_app', 'equipment'),
                ('club_app', 'member'),
            ),
        }
        return allowed_filter_fields

See Component IoC how to register custom Javascript component_class.

It’s possible to specify allowed_filter_fields widget choices, template name and extra options at once:

allowed_filter_fields = {
    'club': {
        'choices': [(club.pk, club.title) for club in Club.objects.filter(category=Club.CATEGORY_PROFESSIONAL)],
        'multiple_choices': False,
        'component_class': 'CustomChoicesFilter',
        # should generate client-side component which uses specified component_class:
        'template': 'custom_choices_widget.htm',
    },
}

It’s also possible to override values of filter template kwargs or to add extra template kwargs with template_kwargs option:

allowed_filter_fields = {
    'content_type': self.get_contenttype_filter(
        'template': 'bs_dropdown.htm',
        'choices':
            ('club_app', 'club'),
            ('club_app', 'equipment'),
            ('club_app', 'member'),
        'template_kwargs': {
            'menu_attrs': {
                'class': 'dropdown-menu dropdown-menu-left'
            }
        },
    ),
}

BaseFilterView interface (grid_fields / allowed_sort_orders / allowed_filter_fields) is inherited by both ListSortingView and by AJAX-based KoGridView (Datatables), which allows to switch between traditional full page server-rendered HTML views and dynamic AJAX views just via changing their parent class name.

Viewmodels views and actions views

  • ViewmodelView - base view; GET request usually generates html template, POST - returns AJAX viewmodels. It is the base class for the following built-in classes:
  • ActionsView - implements AJAX actions router and their viewmodels responses. Actions allow to perform different AJAX POST requests to the same view. The responses are the AJAX viewmodels.
  • ModelFormActionsView - implements AJAX actions specific to Django ModelForm / inline formsets handling: rendering form / validating / saving. It is also the base class for grids (datatables) actions, because the editing of datatables includes form editing via GridActionsMixin.

For introduction to viewmodels, see Client-side viewmodels and AJAX response routing.

For more detailed explanation of these views see AJAX actions.

Datatables

  • KoGridView - together with grid.js allows to create AJAX powered django.admin-like datatables with filtering, sorting, search, CRUD actions and custom actions. See Datatables for more details.

Useful methods / classes of the views module

  • auth_redirect() - authorization required response with redirect to login. Supports ‘next’ url query argument. Supports JSON viewmodel response.
  • cbv_decorator() - may be used to check class-based views permissions.
  • ContextDataMixin - allows to inject pre-defined dict of extra_context_data into template context of class-based view.