Admin Model¶
Example¶
Create the files (e.g. <app_name>/admin_webix.py). The main idea is that many properties and functions that are on views are moved (with some other patameters) directly on admin class. Here there is an example of main list of parameters and functions that can be override.
from <project_name>.admin_webix import site
from django_webix import admin_webix as admin
@admin.register(ModelName, site=site)
class CustomModelWebixAdmin(admin.ModelWebixAdmin):
# WEBIX VIEWS (for fully override)
create_view = None
update_view = None
delete_view = None
list_view = None
# JS TEMPLATES
add_form_template = None
change_form_template = None
change_list_template = None
delete_template = None
# CREATE AND UPDATE SETTINGS
enable_button_save_continue = True
enable_button_save_addanother = True
enable_button_save_gotolist = True
enable_button_save_continue_create = None
enable_button_save_addanother_create = None
enable_button_save_gotolist_create = None
enable_button_save_continue_update = None
enable_button_save_addanother_update = None
enable_button_save_gotolist_update = None
# DJANGO WEBIX FORM: OPTION 1
autocomplete_fields = []
readonly_fields = []
fields = None
exclude = None
# DJANGO WEBIX FORM: OPTION 2
form = None
form_create = None
form_update = None
# INLINES
inlines = []
# FORM STYLE AND RESPONSE
template_form_style = None
label_width = None
errors_on_popup = False
# LIST SETTINGS
ordering = None
actions = []
list_display = []
list_display_header = {} # NEW OVERRIDE HEADER MODALITY
list_editable = []
enable_json_loading = True
paginate_count_default = 100
pk_field = None
title = None
actions_style = None
enable_column_copy = True
model_copy_fields = None
inlines_copy_fields = None
enable_column_delete = True
enable_row_click = True
type_row_click = 'single'
enable_actions = True
remove_disabled_buttons = False
def is_enable_row_click(self, request):
return self.enable_row_click
# GIS
qxs_layers = []
# utils
def get_prefix(self):
return getattr(self, 'prefix', None)
def get_extra_context(self, view=None, request=None):
return {}
def get_queryset(self, view=None, request=None):
return self.model._default_manager.all()
# permission custom
only_superuser = False
def has_add_permission(self, request, view=None):
...
def has_change_permission(self, request, obj=None, view=None):
...
def has_delete_permission(self, request, obj=None, view=None):
...
def has_view_permission(self, request, obj=None, view=None):
...
def get_failure_add_related_objects(self, request):
return []
def get_failure_change_related_objects(self, request):
return []
def get_failure_delete_related_objects(self, request):
return []
def get_failure_view_related_objects(self, request):
return []
def get_info_no_add_permission(self, has_permission, request, view=None):
...
def get_info_no_change_permission(self, has_permission, request, obj=None, view=None):
...
def get_info_no_delete_permission(self, has_permission, request, obj=None, view=None):
...
def get_info_no_view_permission(self, has_permission, request, obj=None, view=None):
...
def get_model_perms(self, request, view=None):
return {
'add': self.has_add_permission(request, view=view),
'change': self.has_change_permission(request, view=view),
'delete': self.has_delete_permission(request, view=view),
'view': self.has_view_permission(request, view=view),
}
def has_module_permission(self, request):
if self.only_superuser:
if request.user.is_superuser:
return True
return False
return super().has_module_permission(request)
def get_add_view(self): # for completly override
...
def get_change_view(self): # for completly override
...
def get_delete_view(self): # for completly override
...
def get_list_view(self): # for completly override
...
# URLS
enable_url_list = True
enable_url_create = True
enable_url_delete = True
enable_url_update = True
def get_urls(self):
_prefix = self.get_prefix()
if _prefix not in [None, '']:
_prefix += '/'
else:
_prefix = ''
_urls = []
if self.enable_url_list == True:
_urls.append(path(_prefix+'', self.get_list_view().as_view(), name=self.get_url_pattern_list()))
if self.enable_url_create == True:
_urls.append(path(_prefix+'create/', self.get_add_view().as_view(), name=self.get_url_pattern_create()))
if self.enable_url_delete == True:
_urls.append(path(_prefix+'<int:pk>/delete/', self.get_delete_view().as_view(), name=self.get_url_pattern_delete()))
if self.enable_url_update == True:
_urls.append(path(_prefix+'<int:pk>/update/', self.get_change_view().as_view(), name=self.get_url_pattern_update()))
return _urls
# EXTRA functions
# in all these functions is added view as parameter
# you can check it with something like this: if issubclass(type(view), WebixCreateView):
# if request is not a parameter you can access ot it by view.request NOT self.request
def dispatch(self, *args, **kwargs)
view = kwargs.pop('view')
return super(view.__class__).dispatch(*args, **kwargs)
def get_url_create_kwargs(self, view=None)
return super(view.__class__).get_url_create_kwargs()
def get_url_create(self, view=None)
return super(view.__class__).get_url_create()
def get_url_update(self, view=None, obj=None)
return super(view.__class__).get_url_update(obj=obj)
def get_url_delete(self, view=None, obj=None)
return super(view.__class__).get_url_delete(obj=obj)
def get_url_list(self, view=None)
return super(view.__class__).get_url_list()
def response_valid(self, view=None, success_url=None, **kwargs):
return super(view.__class__).response_valid(success_url=success_url, **kwargs)
def get_container_id(self, view, request):
def get_form(self, view, form_class):
def get_form_kwargs(self, view):
def pre_forms_valid(self, view, form, inlines, **kwargs):
def post_form_valid(self, view, form, inlines, **kwargs):
def post_forms_valid(self, view, form, inlines, **kwargs):
def get_initial(self, view):
def get_inlines(self, view, object, request):
def get_actions(self, view):
Custom view¶
For each model registration there are a 4 views: CreateView, UpdateView, DeleteView and ListView. You can define directly a CustomView for each view
create_view = None
update_view = None
delete_view = None
list_view = None
or access to a super() costructor by get_XXX_view.
def get_add_view(self):
def get_change_view(self):
def get_delete_view(self):
def get_list_view(self):
Templates¶
For each 4 views is possibile to set custom JS template
add_form_template = None
change_form_template = None
change_list_template = None
delete_template = None
Also you can set specific container to move loading in extra webix template areas.
def get_container_id(self, view, request):
Object / Queryset¶
Each view works on instances. Force queryset is the method that for example based on request can guarantee to check if and user can access to data or not.
ordering = None
def get_queryset(self, view=None, request=None):
return self.model._default_manager.all()
For ListView you can also override PK key.
pk_field = None
Dispatch¶
To not override standard dispatch method, view parameter is injected by kwargs. In this way you can fully managed dispatch of each type of view.
def dispatch(self, *args, **kwargs)
view = kwargs.pop('view')
return super(view.__class__).dispatch(*args, **kwargs)
Permissions¶
Admin area works expecially with database data. There is a fully support for permission management.
only_superuser = False
def has_add_permission(self, request, view=None):
...
def has_change_permission(self, request, obj=None, view=None):
...
def has_delete_permission(self, request, obj=None, view=None):
...
def has_view_permission(self, request, obj=None, view=None):
...
def get_failure_add_related_objects(self, request):
return []
def get_failure_change_related_objects(self, request):
return []
def get_failure_delete_related_objects(self, request):
return []
def get_failure_view_related_objects(self, request):
return []
def get_info_no_add_permission(self, has_permission, request, view=None):
...
def get_info_no_change_permission(self, has_permission, request, obj=None, view=None):
...
def get_info_no_delete_permission(self, has_permission, request, obj=None, view=None):
...
def get_info_no_view_permission(self, has_permission, request, obj=None, view=None):
...
def get_model_perms(self, request, view=None):
return {
'add': self.has_add_permission(request, view=view),
'change': self.has_change_permission(request, view=view),
'delete': self.has_delete_permission(request, view=view),
'view': self.has_view_permission(request, view=view),
}
def has_module_permission(self, request):
if self.only_superuser:
if request.user.is_superuser:
return True
return False
return super().has_module_permission(request)
GIS layer support¶
Mpa Solutions soc coop and Enogis srl have their own GIS module. In this way is possibile to assign qxs_layers to a ModelAdmin to better interactive support.
qxs_layers = []
Buttons¶
In all views there are buttons. If you disable some of then is possibile to remove it by this settings.
remove_disabled_buttons
Multiple model admin registration¶
If if needed multiple Model registration you have to pass to register decorato a specific prefix for each registration.
prefix
def get_prefix(self):
return getattr(self, 'prefix', None)
Context view¶
It’s possibile to set an extra context when is required into a specific or all views.
def get_extra_context(self, view=None, request=None):
return {}
Buttons save in UpdateView and CreateView¶
Into UpdateView and CreateView is possibile to show/hide each of 3 main save buttons.
enable_button_save_continue = True
enable_button_save_addanother = True
enable_button_save_gotolist = True
enable_button_save_continue_create = None
enable_button_save_addanother_create = None
enable_button_save_gotolist_create = None
enable_button_save_continue_update = None
enable_button_save_addanother_update = None
enable_button_save_gotolist_update = None
Form/Inline in UpdateView and CreateView¶
In UpdateView and CreateView is possibile to set custom form.
form = None
form_create = None
form_update = None
or like standard django admin give all fields and caracteristics.
autocomplete_fields = []
readonly_fields = []
fields = None
exclude = None
also you can set some inlines:
inlines = []
You can customizate also form with width of label and style of form.
template_form_style = None
label_width = None
When you want block user on errors you can show these into a popup with a read confirm button.
errors_on_popup = False
In terms of form support for CreateView and UpdateView is possibile override form and inlines creation and data insert.
def get_form(self, view, form_class):
def get_form_kwargs(self, view):
def get_initial(self, view):
def get_inlines(self, view, object, request):
Valid sequentiality UpdateView and CreateView¶
Some extra function are available for better interact with complete save process.
def pre_forms_valid(self, view, form, inlines, **kwargs):
def post_form_valid(self, view, form, inlines, **kwargs):
def post_forms_valid(self, view, form, inlines, **kwargs):
Valid sequentiality DeleteView¶
Some extra function are available for better interact with complete delete process.
def pre_delete_valid(self, **kwargs):
django_webix_view_pre_delete.send(sender=self, instance=self.object)
def post_delete_valid(self, **kwargs):
django_webix_view_post_delete.send(sender=self, instance=self.copied_object)
Response valid for DeleteView, UpdateViev and CreateView¶
After valid operation is possibile to customize the response.
def response_valid(self, view=None, success_url=None, **kwargs):
return super(view.__class__).response_valid(success_url=success_url, **kwargs)
List columns¶
Main List settings are the same that you can see into django-admin standard for column definition.
list_display = []
list_editable = []
It’s also possibile force header template by
list_display_header = {}
List actions¶
Like for generical ListView is possibile to fully manage actions.
enable_actions = True
actions = []
actions_style = None
def get_actions(self, view):
List data loading¶
Admin support fully ListView paging.
enable_json_loading = True
paginate_count_default = 100
List rows and columns¶
It’s possibile to manage function on columns as Copy and Delete buttons and you can also define how rows are selected.
enable_column_copy = True
model_copy_fields = None
inlines_copy_fields = None
enable_column_delete = True
enable_row_click = True
type_row_click = 'single'
def is_enable_row_click(self, request):
return self.enable_row_click
Urls¶
There is a complete set of functions for manage urls.
You can enable or disable urls.
enable_url_list = True
enable_url_create = True
enable_url_delete = True
enable_url_update = True
Or if you want add others urls on a ModelAdmin registration you can override get_urls.
def get_urls(self):
_prefix = self.get_prefix()
if _prefix not in [None, '']:
_prefix += '/'
else:
_prefix = ''
_urls = []
if self.enable_url_list == True:
_urls.append(path(_prefix+'', self.get_list_view().as_view(), name=self.get_url_pattern_list()))
if self.enable_url_create == True:
_urls.append(path(_prefix+'create/', self.get_add_view().as_view(), name=self.get_url_pattern_create()))
if self.enable_url_delete == True:
_urls.append(path(_prefix+'<int:pk>/delete/', self.get_delete_view().as_view(), name=self.get_url_pattern_delete()))
if self.enable_url_update == True:
_urls.append(path(_prefix+'<int:pk>/update/', self.get_change_view().as_view(), name=self.get_url_pattern_update()))
return _urls
Or if you want override standard path you can override functions that get pattern urls.
def get_url_create_kwargs(self, view=None)
return super(view.__class__).get_url_create_kwargs()
def get_url_create(self, view=None)
return super(view.__class__).get_url_create()
def get_url_update(self, view=None, obj=None)
return super(view.__class__).get_url_update(obj=obj)
def get_url_delete(self, view=None, obj=None)
return super(view.__class__).get_url_delete(obj=obj)
def get_url_list(self, view=None)
return super(view.__class__).get_url_list()