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 :py:class:`~djcrud.views.list.ListView` on ``Article`` * ``action_example`` — object form action on ``Memo`` * ``listaction_example`` — bulk action on ``Post`` * ``search_example`` — :func:`~djcrud.search.add_search` opt-in on ``Page`` ListView customization ---------------------- :py:class:`~djcrud.views.list.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: .. literalinclude:: ../../src/djcrud_example/views_example/djcrud.py No ``add_perm`` here — default Django permissions apply (superuser passes). Log in as ``su`` / ``su`` (see :doc:`routing`). Permission rules are covered in :doc:`permission` and the ``security_example`` app. Visit `http://localhost:8000/article/ `_. .. figure:: /_static/screenshots/article-list.png :alt: Article list with filter form and pagination :align: center :width: 90% 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** :py:class:`~djcrud.views.objectform.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): .. literalinclude:: ../../src/djcrud_example/action_example/djcrud.py Try it on a memo at `http://localhost:8000/memo// `_. .. figure:: /_static/screenshots/duplicate-action-menu.png :alt: Object menu with Duplicate action on a memo :align: center :width: 90% Detail object menu with a custom object action. .. figure:: /_static/screenshots/duplicate-action-success.png :alt: Memo detail after duplicating :align: center :width: 90% After confirming, a success toast is shown. State-based object actions gated by ``add_perm`` are covered in :doc:`permission`. List action ----------- Bulk actions follow the same pattern as built-in bulk delete (see :doc:`routing`). On ``Post``, subclass :py:class:`~djcrud.views.list_action.ListActionView`, tag it ``list_action``, and append it to the router ``routes``: .. literalinclude:: ../../src/djcrud_example/listaction_example/djcrud.py Try it at `http://localhost:8000/post/ `_ — create a few posts, select rows, and click **Set category**: .. figure:: /_static/screenshots/list-action-bar.png :alt: List action bar with row selection :align: center :width: 90% Selected rows open the floating ```` 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. .. figure:: /_static/screenshots/set-category-modal.png :alt: Set category bulk action modal :align: center :width: 90% Custom :py:class:`SetCategoryView` — same pattern as the built-in bulk delete shown in :doc:`routing`. Site search ----------- With ``djcrud_dal_topbar`` installed (see :ref:`install-site-search`), opt a model into navbar search and the results page at ``/search/?q=…``. ``search_example`` registers its own ``Page`` model: .. literalinclude:: ../../src/djcrud_example/search_example/djcrud.py Try it at `http://localhost:8000/page/ `_ after creating a few pages, then search from the navbar. 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 :doc:`../reference/mixins/index` for every mixin and overridable attribute. Generic views that combine them are listed under :doc:`../reference/views/index`. For screenshots of list, filter, pagination, object-menu, and list-action mixins in action, see the sections above. List display :py:class:`~djcrud.views.list.ListMixin` — :attr:`~djcrud.views.list.ListMixin.default_template_name`, :attr:`~djcrud.views.list.ListMixin.tags`, :attr:`~djcrud.views.list.ListMixin.permission_shortcode`, :attr:`~djcrud.views.list.ListMixin.empty_list_message` :py:class:`~djcrud.views.search.SearchMixin` — :attr:`~djcrud.views.search.SearchMixin.search_param`, :attr:`~djcrud.views.search.SearchMixin.search_fields` :py:class:`~djcrud.views.filter.FilterMixin` — :attr:`~djcrud.views.filter.FilterMixin.filter_fields`, :attr:`~djcrud.views.filter.FilterMixin.filter_form_class`, :attr:`~djcrud.views.filter.FilterMixin.filter_target` :py:class:`~djcrud.views.pagination.PaginationMixin` — :attr:`~djcrud.views.pagination.PaginationMixin.paginate_by`, :attr:`~djcrud.views.pagination.PaginationMixin.per_page_options`, :attr:`~djcrud.views.pagination.PaginationMixin.page_kwarg`, :attr:`~djcrud.views.pagination.PaginationMixin.per_page_kwarg`, :attr:`~djcrud.views.pagination.PaginationMixin.pagination_target` :py:class:`~djcrud.views.tables2.Tables2Mixin` — :attr:`~djcrud.views.tables2.Tables2Mixin.table_template`, :attr:`~djcrud.views.tables2.Tables2Mixin.table_fields` Forms and objects :py:class:`~djcrud.views.form.FormMixin` — :attr:`~djcrud.views.form.FormMixin.default_template_name`, :attr:`~djcrud.views.form.FormMixin.form_attributes` :py:class:`~djcrud.views.object.ObjectMixin` — object detail URLs and breadcrumbs (see :doc:`../reference/mixins/object`) :py:class:`~djcrud.views.modelform.ModelFormMixin` — model forms for create/update :py:class:`~djcrud.views.delete.DeleteMixin` — :attr:`~djcrud.views.delete.DeleteMixin.default_template_name`, :attr:`~djcrud.views.delete.DeleteMixin.icon`, :attr:`~djcrud.views.delete.DeleteMixin.color` List actions and permissions :py:class:`~djcrud.views.list_action.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 ```` via ``data-list-actions`` / ``data-codename`` attributes. :py:class:`~djcrud.views.action.ActionMixin` — per-object permission checks on delete/update and custom object actions :py:class:`~djcrud.view.ViewMixin` — :attr:`~djcrud.view.ViewMixin.permission_shortcode` Templates and model binding :py:class:`~djcrud.views.template.TemplateViewMixin` — :attr:`~djcrud.views.template.TemplateMixin.default_template_name` via ``default_template_name`` on concrete views :py:class:`~djcrud.model.ModelMixin` — resolves ``model`` from the enclosing :py:class:`~djcrud.ModelRouter` :py:class:`~djcrud.views.log.LogMixin` — audit logging when ``djcrud_history`` is installed Further topics Optional packages (history, debug, auth) are described in :doc:`../install`. 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 ----- * `tests/test_views_example.py `_ * `tests/test_action_example.py `_ * `tests/test_listaction_example.py `_ * `tests/test_search_example.py `_ Next: :doc:`drf` adds an optional JSON API; :doc:`spa` adds the SPA shell and client codegen.