CRUD Viewset

CRUD or create, read, update, and delete are the four basic functions on Django Model. Viewflow provides ready-to-use CRUD viewsets, views, and templates based on google material design. Combined all together they allow to implement Django admin like functionality.

You can quickly instantiate a Viewset by passing required parameters to a class constructor

from viewflow import Icon
from viewflow.urls import ReadonlyModelViewset, ModelViewset

categories_viewset = ReadonlyModelViewset(
    app_name='category',
    icon=Icon('category'),
    model=models.Category,
    list_view=views.custom_list_view,
)

Or inherit from a viewset class and override methods and attributes

class DepartmentViewset(ModelViewset):
    icon = Icon('people')
    model = models.Department
    list_columns = ('name', 'manager', 'parent')
    list_filter_fields = ('parent', )

After inclusion into an Application viewset, you will get a model list page with links points to model details or edit pages.

ModelViewset is the viewset that mixes list model view with create/update views. Use DetailViewMixin to point links from list view to model detail page, before change form. DetailViewMixin adds ability to delete a model instance.

ReadonlyModelViewset only list a model and provide model details page.

Basic options

The only mandatory option for CRUD viewsets is the model class. You would also like to customize icon and title appearance in the site menu.

To optimize querying or restrict models listed, specify queryset attribute or override get_queryset method.

class EmployeeViewset(DetailViewMixin, ModelViewset):
    model = models.Employee
    queryset = model._default_manager.select_related('department')

    def get_queryset(self, request);
         if not request.user.is_staff:
              return self.queryset.exclude(department__parent_isnull=True)
         return self.queryset

You can replace a build-in view with our own functional or class-based view. Or pass additional keyword parameters to .as_view call

list_view_class = views.EmployeeListView
create_view = views.create_employee_view

def get_update_view_kwargs(self):
    return {
        'success_url': reverse('emp:employee:index')
    }

As for any viewset, you can add additional views, just by adding an attribute named with _url suffix

manager_change_url =  path(
    '<path:pk>/manages/', views.change_manager, name='change_manager'
)

Form options

TODO

List options

list_columns

Set list_columns to control which fields are displayed on the change list view.

If you don’t set list_columns, the list view will display a single column that with __str__() representation of each object.

There are three types of values that can be used in list_display:

The name of a model field. For example:

class EmployeeViewset(ModelViewset):
    list_columns = ('first_name', 'last_name')

A string representing a Viewset method that accepts one argument, the model instance. For example:

class EmployeeViewset(ModelViewset):
    list_columns = ('upper_case_name',)

    def upper_case_name(self, obj):
        return ("%s %s" % (obj.first_name, obj.last_name)).upper()
    upper_case_name.short_description = 'Name'

Or a string representing a model attribute or method (without any required arguments)

list_page_actions

TODO

List filterset

TODO list_filter_class list_filter_fields

Permissions

Viewflow CRUd viewsets check standard Django add/change/delete/view user per-object permissions. Unlike default django behavior, if user have no-object specific permission, for example if user.has_perm(‘myapp.change_employee’, obj=None) equals True, default viewflow behavior is to assume that user have the permission for all objects. on if has_perm with obj=None return False object specific permission is checked. You can override in corresponding has_view_permission, has_add_permission, has_change_permission, has_delete_permission methods.

def has_delete_permission(self, request, obj=None):
    return request.user.is_staff

Views

Pre-built views for admin like interfaces. All viewflow.views are inherited from core Django generic views with very few additions and method redefinitions.

All of them are accepts viewset as keyword parameter for the .as_view() method. If viewset present, the viewset methods and options would be used, permission checking methods like has_add_permission need to be overridden only in a viewset, and they would be used by a view. Same for get_queryset method.