Views

Goal

Replace default views, add object actions, register bulk list actions, and opt models into site-wide search. Four tutorial apps each ship a single djcrud.py — no extra modules:

  • views_example — cloned ListView on Article

  • action_example — object form action on Memo

  • listaction_example — bulk action on Post

  • search_exampleadd_search() opt-in on Page

ListView customization

ListView is the view djcrud invests in by default — search, filter, tables2, pagination, and list actions. Clone it to set table columns, filter fields, and page size:

import djcrud

from .models import Article


class ArticleRouter(djcrud.ModelRouter):
    model = Article
    icon = "newspaper"

    routes = djcrud.ModelRouter.routes + [
        djcrud.views.ListView.clone(
            table_fields=["title", "category"],
            filter_fields=["category"],
            paginate_by=5,
        ),
    ]


djcrud.site.routes.append(ArticleRouter)

No add_perm here — default Django permissions apply (superuser passes). Log in as su / su (see Routing). Permission rules are covered in Permissions and the security_example app.

Visit http://localhost:8000/article/.

Article list with filter form and pagination

Cloned list view with custom columns, filter fields, and page size.

Object action

Custom routes are not limited to CRUD. action_example appends a Duplicate ObjectFormView that opens a confirmation modal from the object menu and calls form_valid — no add_perm here (default superuser access, same as the list view above):

import djcrud

from .models import Memo


class DuplicateView(djcrud.views.ObjectFormView):
    title = "Duplicate"
    icon = "copy"
    color = "info"

    def form_valid(self, form):
        Memo.objects.create(title=f"{self.object.title} (copy)")
        return super().form_valid(form)


class MemoRouter(djcrud.ModelRouter):
    model = Memo
    icon = "stickies"

    routes = djcrud.ModelRouter.routes + [DuplicateView]


djcrud.site.routes.append(MemoRouter)

Try it on a memo at http://localhost:8000/memo/<pk>/.

Object menu with Duplicate action on a memo

Detail object menu with a custom object action.

Memo detail after duplicating

After confirming, a success toast is shown.

State-based object actions gated by add_perm are covered in Permissions.

List action

Bulk actions follow the same pattern as built-in bulk delete (see Routing). On Post, subclass ListActionView, tag it list_action, and append it to the router routes:

from django import forms

import djcrud

from .models import Post


class SetCategoryForm(forms.Form):
    category = forms.CharField(max_length=50, label="Category")


class SetCategoryView(djcrud.views.ListActionView):
    permission_shortcode = "change"
    title = "Set category"
    icon = "tag"
    color = "info"
    message = "Choose a category for the selected posts."
    form_class = SetCategoryForm

    def form_valid(self, form):
        self.object_list.update(category=form.cleaned_data["category"])
        return super().form_valid(form)


class PostRouter(djcrud.ModelRouter):
    model = Post
    icon = "chat-square-text"

    routes = djcrud.ModelRouter.routes + [
        SetCategoryView,
    ]


djcrud.site.routes.append(PostRouter)

Try it at http://localhost:8000/post/ — create a few posts, select rows, and click Set category:

List action bar with row selection

Selected rows open the floating <list-action-bar> with permitted bulk actions. When list actions are gated per object, only rows the user may act on get checkboxes, and the bar dynamically shows only the actions allowed for the entire current selection.

Set category bulk action modal

Custom SetCategoryView — same pattern as the built-in bulk delete shown in Routing.

Mixin survey

djcrud builds each generic view from mixins — small classes that add one concern (filtering, pagination, tables, forms, …). Override mixin attributes on a cloned view or subclass; templates read them from the view object in context.

See View mixins for every mixin and overridable attribute. Generic views that combine them are listed under Generic views.

For screenshots of list, filter, pagination, object-menu, and list-action mixins in action, see the sections above.

List display

ListMixindefault_template_name, tags, permission_shortcode, empty_list_message

SearchMixinsearch_param, search_fields

FilterMixinfilter_fields, filter_form_class, filter_target

PaginationMixinpaginate_by, per_page_options, page_kwarg, per_page_kwarg, pagination_target

Tables2Mixintable_template, table_fields

Forms and objects

FormMixindefault_template_name, form_attributes

ObjectMixin — object detail URLs and breadcrumbs (see ObjectMixin)

ModelFormMixin — model forms for create/update

DeleteMixindefault_template_name, icon, color

List actions and permissions

ListActionMixin — bulk actions from the list action bar (see List action above). Per-row permissions are reflected both in checkbox visibility (CheckboxColumn) and in the dynamic filtering of buttons inside <list-action-bar> via data-list-actions / data-codename attributes.

ActionMixin — per-object permission checks on delete/update and custom object actions

ViewMixinpermission_shortcode

Templates and model binding

TemplateViewMixindefault_template_name via default_template_name on concrete views

ModelMixin — resolves model from the enclosing ModelRouter

LogMixin — audit logging when djcrud_history is installed

Further topics

Optional packages (history, debug, auth) are described in Install djcrud.

Menus and tags — tag views with navigation, object, or list_action. Use router.get_tagged_views('object', request=request, object=obj) in templates.

Runtime route changes — after site.build(), swap or remove routes on the live registry (site.routes['list'] = , del site.routes['delete']).

Routing debug — add djcrud_debug and browse http://localhost:8000/debug/router/ as superuser.

Tests

Next: DRF API adds an optional JSON API; SPA shell adds the SPA shell and client codegen.