GenericListView¶
Generated view class for ListAction.
GenericListView
¶
djadmin.factories.base.GenericListView
ListAction View class for site.None generated by ViewFactory.
Base class: django.views.generic.list.ListView Mixins: DjAdminFiltersMixin, PermissionMixin, DjAdminViewMixin, SearchMixin Active plugins: djadmin.plugins.contrib_auth, examples.webshop, djadmin_formset, djadmin_classy_doc, djadmin_filters, djadmin.plugins.permissions, djadmin.plugins.core, djadmin.plugins.theme
View Information ¶
- Action
ListAction- ModelAdmin
djadmin.options.ModelAdmin
View Construction ¶
Base Class
django.views.generic.list.ListView
Mixins
-
djadmin_filters.mixins.DjAdminFiltersMixindjadmin_filters.djadmin_hooks -
djadmin.plugins.permissions.mixins.PermissionMixindjadmin.plugins.permissions.djadmin_hooks -
djadmin.plugins.core.mixins.DjAdminViewMixindjadmin.plugins.core.djadmin_hooks -
djadmin.plugins.core.mixins.SearchMixindjadmin.plugins.core.djadmin_hooks
Bound Methods from Action
-
get_template_names()from ListAction -
get_queryset()from ListAction -
get_context_data()from ListAction
Method Resolution Order ¶
-
djadmin.factories.base.GenericListView -
djadmin_filters.mixins.DjAdminFiltersMixindjadmin_filters.djadmin_hooks -
django_filters.views.FilterMixin -
djadmin.plugins.permissions.mixins.PermissionMixindjadmin.plugins.permissions.djadmin_hooks -
django.contrib.auth.mixins.UserPassesTestMixin -
django.contrib.auth.mixins.AccessMixin -
djadmin.plugins.core.mixins.DjAdminViewMixindjadmin.plugins.core.djadmin_hooks -
djadmin.plugins.core.mixins.SearchMixindjadmin.plugins.core.djadmin_hooks -
django.views.generic.list.ListViewbase class from ListAction -
django.views.generic.list.MultipleObjectTemplateResponseMixin -
django.views.generic.base.TemplateResponseMixin -
django.views.generic.list.BaseListView -
django.views.generic.list.MultipleObjectMixin -
django.views.generic.base.ContextMixin -
django.views.generic.base.View
Attributes ¶
| Attribute | Value | Defined in |
|---|---|---|
action |
ListAction() |
djadmin.factories.base.GenericListView
|
admin_site |
AdminSite(name='docs_temp') |
djadmin.factories.base.GenericListView
|
allow_empty |
True |
django.views.generic.list.MultipleObjectMixin
|
column_header_icons |
[ColumnHeaderIcon(icon_template=get_sort_icon_template(),... |
djadmin.factories.base.GenericListView
|
content_type |
None |
django.views.generic.base.TemplateResponseMixin
|
context_object_name |
None |
django.views.generic.list.MultipleObjectMixin
|
extra_context |
None |
django.views.generic.base.ContextMixin
|
filterset_class |
None |
django_filters.views.FilterMixin
|
filterset_fields |
__all__ |
django_filters.views.FilterMixin
|
http_method_names |
['get', 'post', 'put', 'patch', 'delete', 'head', 'option... |
django.views.generic.base.View
|
login_url |
None |
django.contrib.auth.mixins.AccessMixin
|
model |
None |
django.views.generic.list.MultipleObjectMixin
|
model_admin |
ModelAdmin() |
djadmin.factories.base.GenericListView
|
ordering |
None |
django.views.generic.list.MultipleObjectMixin
|
page_kwarg |
page |
django.views.generic.list.MultipleObjectMixin
|
paginate_by |
None |
django.views.generic.list.MultipleObjectMixin
|
paginate_orphans |
0 |
django.views.generic.list.MultipleObjectMixin
|
paginator_class |
django.core.paginator.Paginator |
django.views.generic.list.MultipleObjectMixin
|
permission_denied_message |
|
django.contrib.auth.mixins.AccessMixin
|
queryset |
None |
django.views.generic.list.MultipleObjectMixin
|
raise_exception |
False |
django.contrib.auth.mixins.AccessMixin
|
redirect_field_name |
next |
django.contrib.auth.mixins.AccessMixin
|
response_class |
django.template.response.TemplateResponse |
django.views.generic.base.TemplateResponseMixin
|
sidebar_widgets |
[SidebarWidget(template='djadmin/djadmin_filters/filter_w... |
djadmin.factories.base.GenericListView
|
strict |
True |
django_filters.views.FilterMixin
|
template_engine |
None |
django.views.generic.base.TemplateResponseMixin
|
template_name |
None |
django.views.generic.base.TemplateResponseMixin
|
template_name_suffix |
_list |
django.views.generic.list.MultipleObjectTemplateResponseMixin
|
view_is_async |
False |
django.views.generic.base.View
|
Methods ¶
__init__(self, **kwargs)
Defined in:
<class 'django.views.generic.base.View'>
Constructor. Called in the URLconf; can contain helpful extra keyword arguments, and other things.
Source code
in base.py
line 54
def __init__(self, **kwargs):
"""
Constructor. Called in the URLconf; can contain helpful extra
keyword arguments, and other things.
"""
# Go through keyword arguments, and either save their values to our
# instance, or raise an error.
for key, value in kwargs.items():
setattr(self, key, value)
apply_search(self, queryset)
Defined in:
<class 'djadmin.plugins.core.mixins.SearchMixin'>
Apply search filtering to the queryset.
Args: queryset: The base queryset to filter
Returns: Filtered queryset with search applied
Source code
in mixins.py
line 475
def apply_search(self, queryset):
"""
Apply search filtering to the queryset.
Args:
queryset: The base queryset to filter
Returns:
Filtered queryset with search applied
"""
search_query = self.get_search_query()
search_fields = self.get_search_fields()
if not search_query or not search_fields:
return queryset
# Detect if we're using PostgreSQL
if self._is_postgresql():
return self._apply_search_postgresql(queryset, search_query, search_fields)
else:
return self._apply_search_generic(queryset, search_query, search_fields)
as_view(**initkwargs)
@classmethod
Defined in:
<class 'django.views.generic.base.View'>
Main entry point for a request-response process.
Source code
in base.py
line 81
@classonlymethod
def as_view(cls, **initkwargs):
"""Main entry point for a request-response process."""
for key in initkwargs:
if key in cls.http_method_names:
raise TypeError(
"The method name %s is not accepted as a keyword argument "
"to %s()." % (key, cls.__name__)
)
if not hasattr(cls, key):
raise TypeError(
"%s() received an invalid keyword %r. as_view "
"only accepts arguments that are already "
"attributes of the class." % (cls.__name__, key)
)
def view(request, *args, **kwargs):
self = cls(**initkwargs)
self.setup(request, *args, **kwargs)
if not hasattr(self, "request"):
raise AttributeError(
"%s instance has no 'request' attribute. Did you override "
"setup() and forget to call super()?" % cls.__name__
)
return self.dispatch(request, *args, **kwargs)
view.view_class = cls
view.view_initkwargs = initkwargs
# __name__ and __qualname__ are intentionally left unchanged as
# view_class should be used to robustly determine the name of the view
# instead.
view.__doc__ = cls.__doc__
view.__module__ = cls.__module__
view.__annotations__ = cls.dispatch.__annotations__
# Copy possible attributes set by decorators, e.g. @csrf_exempt, from
# the dispatch method.
view.__dict__.update(cls.dispatch.__dict__)
# Mark the callback if the view class is async.
if cls.view_is_async:
markcoroutinefunction(view)
return view
build_form(self, form=None)
Defined in:
<class 'djadmin.plugins.core.mixins.DjAdminViewMixin'>
Build form class from layout or fields. Override in plugins to customize.
This method is called by get_form_class() when no explicit form_class is provided. The default implementation uses FormBuilder to create forms from layouts or fields.
Returns: ModelForm class ready for instantiation
Source code
in mixins.py
line 246
def build_form(self, form=None):
"""
Build form class from layout or fields. Override in plugins to customize.
This method is called by get_form_class() when no explicit form_class is provided.
The default implementation uses FormBuilder to create forms from layouts or fields.
Returns:
ModelForm class ready for instantiation
"""
layout = self.get_layout()
if layout:
# Build from layout using FormBuilder
print('using FormBuilder.from_layout')
return FormBuilder.from_layout(layout, self.model, form_class=None)
print('using FormBuilder.create_form')
# No layout - build from fields
fields = getattr(self, 'get_fields', lambda: '__all__')()
return FormBuilder.create_form(self.model, fields=fields)
dispatch(self, request, *args, **kwargs)
Defined in:
<class 'django.views.generic.base.View'>
Source code
in base.py
line 134
def dispatch(self, request, *args, **kwargs):
# Try to dispatch to the right method; if a method doesn't exist,
# defer to the error handler. Also defer to the error handler if the
# request method isn't on the approved list.
if request.method.lower() in self.http_method_names:
handler = getattr(
self, request.method.lower(), self.http_method_not_allowed
)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)
Source code
in mixins.py
line 131
def dispatch(self, request, *args, **kwargs):
user_test_result = self.get_test_func()()
if not user_test_result:
return self.handle_no_permission()
return super().dispatch(request, *args, **kwargs)
filtered_actions
Defined in:
<class 'djadmin.plugins.core.mixins.DjAdminViewMixin'>
Filtered action lists by user permissions, cached on view instance.
For object-based views (UpdateView, DetailView, DeleteView), filters actions based on the specific object. For list views, filters at model level.
Results are cached on the view instance, which is per-request since Django creates a new view instance for each request. Combined with request-level caching in ModelAdmin.filter_actions(), this ensures actions are filtered only once per request.
Performance Impact: Without caching: Actions filtered multiple times per request With caching: Actions filtered once per request (view instance)
Returns: dict: Dictionary with filtered action lists: - filtered_general_actions - filtered_bulk_actions - filtered_record_actions
get(self, request, *args, **kwargs)
Defined in:
<class 'django.views.generic.list.BaseListView'>
Source code
in list.py
line 157
def get(self, request, *args, **kwargs):
self.object_list = self.get_queryset()
allow_empty = self.get_allow_empty()
if not allow_empty:
# When pagination is enabled and object_list is a queryset,
# it's better to do a cheap query than to load the unpaginated
# queryset in memory.
if self.get_paginate_by(self.object_list) is not None and hasattr(
self.object_list, "exists"
):
is_empty = not self.object_list.exists()
else:
is_empty = not self.object_list
if is_empty:
raise Http404(
_("Empty list and “%(class_name)s.allow_empty” is False.")
% {
"class_name": self.__class__.__name__,
}
)
context = self.get_context_data()
return self.render_to_response(context)
get_allow_empty(self)
Defined in:
<class 'django.views.generic.list.MultipleObjectMixin'>
Return True if the view should display empty lists and False
if a 404 should be raised instead.
Source code
in list.py
line 106
def get_allow_empty(self):
"""
Return ``True`` if the view should display empty lists and ``False``
if a 404 should be raised instead.
"""
return self.allow_empty
get_context_data(self, **kwargs)
Defined in:
<class 'django.views.generic.base.ContextMixin'>
Source code
in actions.py
line 231
def get_context_data(self, **kwargs):
"""
Add list_display to template context.
When bound to the view, self is the view instance.
Calls DjAdminViewMixin.get_context_data() via super() to get base admin context.
Note: Action filtering is now handled automatically by DjAdminViewMixin.get_context_data()
"""
# Call super to get base context from DjAdminViewMixin
# This now includes filtered actions automatically
context = super(type(self), self).get_context_data(**kwargs)
# Add list_display for template iteration
context['list_display'] = self.model_admin.list_display
return context
Source code
in list.py
line 122
def get_context_data(self, *, object_list=None, **kwargs):
"""Get the context for this view."""
queryset = object_list if object_list is not None else self.object_list
page_size = self.get_paginate_by(queryset)
context_object_name = self.get_context_object_name(queryset)
if page_size:
paginator, page, queryset, is_paginated = self.paginate_queryset(
queryset, page_size
)
context = {
"paginator": paginator,
"page_obj": page,
"is_paginated": is_paginated,
"object_list": queryset,
}
else:
context = {
"paginator": None,
"page_obj": None,
"is_paginated": False,
"object_list": queryset,
}
if context_object_name is not None:
context[context_object_name] = queryset
context.update(kwargs)
return super().get_context_data(**context)
Source code
in mixins.py
line 126
def get_context_data(self, **kwargs):
"""
Add standard admin context to all views.
When bound to the view, self is the view instance which has:
- self.action: Action instance
- self.model: Model class
- self.model_admin: ModelAdmin instance
- self.admin_site: AdminSite instance
- self.request: Current request
"""
from djadmin.plugins import pm
# Call super to get base context from Django CBV
context = super().get_context_data(**kwargs)
# Add request to context (needed for inclusion tags)
context['request'] = self.request
# Add standard admin context
context['model'] = self.model
context['opts'] = self.model._meta if self.model else None
context['action'] = self.action
context['model_admin'] = self.model_admin
context['admin_site'] = self.admin_site
# Add version information
context['djadmin_version'] = djadmin.__version__
context['django_version'] = django.get_version()
# Add site-wide URLs
try:
context['index_url'] = reverse(f'{self.admin_site.name}:index')
except Exception:
context['index_url'] = '/'
# Add site configuration
context['site_header'] = self.admin_site.site_header
context['site_title'] = self.admin_site.site_title
context['index_title'] = self.admin_site.index_title
# Add list URL (using admin_site namespace)
# Skip for site-level actions (model=None)
if self.model is not None:
list_url_name = f'{self.model_admin.list_url_name}'
context['list_url'] = self.admin_site.reverse(list_url_name)
else:
context['list_url'] = context.get('index_url', '/')
# Add namespaced URL names for actions
namespace = self.admin_site.name
context['action_namespace'] = namespace
# Add breadcrumbs
context['breadcrumb_list'] = self._get_breadcrumbs()
# Add assets from plugins
assets = self._get_assets_from_plugins()
context['assets'] = assets
# Add sidebar widgets for template rendering
sidebar_widgets = self._get_sidebar_widgets_for_template()
context['sidebar_widgets'] = sidebar_widgets
# Add column header icons for list views
column_header_icons = self._get_column_header_icons()
context['column_header_icons'] = column_header_icons
# Add filtered actions to context (permission-checked)
# This ensures all views (ListView, UpdateView, CreateView, etc.) get filtered actions
if self.model is not None and self.model_admin is not None:
# Add unfiltered action lists (for template tag use in ListView)
context['general_actions'] = self.model_admin.general_actions
context['bulk_actions'] = self.model_admin.bulk_actions
context['record_actions'] = self.model_admin.record_actions
# Add filtered action lists (for use in templates)
context.update(self.filtered_actions)
# Allow plugins to add more context
plugin_contexts = pm.hook.djadmin_add_context_data(
context=context,
request=self.request,
view=self,
)
for plugin_context in plugin_contexts:
if plugin_context:
context.update(plugin_context)
if settings.DEBUG:
# List loaded plugins for debugging
# djp.PluginManager wraps pluggy, access the underlying manager
try:
# Get plugins from the underlying pluggy manager
if hasattr(pm, '_pm'):
# djp stores the pluggy manager as _pm
plugins = pm._pm.get_plugins()
elif hasattr(pm, 'get_plugins'):
plugins = pm.get_plugins()
else:
# Fallback: just note that we couldn't list plugins
plugins = ['(plugin listing not available)']
context['debug_loaded_plugins'] = [str(plugin) for plugin in plugins]
except Exception as e:
context['debug_loaded_plugins'] = [f'Error listing plugins: {e}']
# Debug: Show view's MRO (Method Resolution Order) to see which mixins are applied
context['debug_view_mro'] = [cls.__name__ for cls in self.__class__.__mro__[:10]]
# Debug: Show form class being used
if hasattr(self, 'form_class'):
context['debug_form_class'] = str(self.form_class)
# Debug: Show action class hierarchy
context['debug_action_mro'] = [cls.__name__ for cls in self.action.__class__.__mro__[:10]]
return context
Source code
in mixins.py
line 143
def get_context_data(self, **kwargs):
"""
Add FilterSet to template context.
Returns:
Context dict with 'filterset' added
"""
context = super().get_context_data(**kwargs)
# Add filterset to context if it exists
if hasattr(self, 'filterset'):
context['filterset'] = self.filterset
# Check if any filter fields have values (excluding search/ordering/page)
# This helps templates show/hide the clear button appropriately
context['has_active_filters'] = self._has_active_filters()
# Provide a clean URL for clearing filters (keeps search and ordering)
context['clear_filters_url'] = self._get_clear_filters_url()
return context
Source code
in actions.py
line 231
def get_context_data(self, **kwargs):
"""
Add list_display to template context.
When bound to the view, self is the view instance.
Calls DjAdminViewMixin.get_context_data() via super() to get base admin context.
Note: Action filtering is now handled automatically by DjAdminViewMixin.get_context_data()
"""
# Call super to get base context from DjAdminViewMixin
# This now includes filtered actions automatically
context = super(type(self), self).get_context_data(**kwargs)
# Add list_display for template iteration
context['list_display'] = self.model_admin.list_display
return context
get_context_object_name(self, object_list)
Defined in:
<class 'django.views.generic.list.MultipleObjectMixin'>
Get the name of the item to be used in the context.
Source code
in list.py
line 113
def get_context_object_name(self, object_list):
"""Get the name of the item to be used in the context."""
if self.context_object_name:
return self.context_object_name
elif hasattr(object_list, "model"):
return "%s_list" % object_list.model._meta.model_name
else:
return None
get_filterset(self, filterset_class)
Defined in:
<class 'django_filters.views.FilterMixin'>
Returns an instance of the filterset to be used in this view.
Source code
in views.py
line 33
def get_filterset(self, filterset_class):
"""
Returns an instance of the filterset to be used in this view.
"""
kwargs = self.get_filterset_kwargs(filterset_class)
return filterset_class(**kwargs)
Source code
in mixins.py
line 50
def get_filterset(self, filterset_class):
"""
Instantiate the FilterSet with request data.
Args:
filterset_class: The FilterSet class to instantiate
Returns:
FilterSet instance, or None if no filterset_class
"""
if filterset_class is None:
return None
# Get the base queryset
queryset = self.get_queryset_for_filter()
# Instantiate FilterSet with request GET data
return filterset_class(self.request.GET, queryset=queryset, request=self.request)
get_filterset_class(self)
Defined in:
<class 'django_filters.views.FilterMixin'>
Returns the filterset class to use in this view
Source code
in views.py
line 21
def get_filterset_class(self):
"""
Returns the filterset class to use in this view
"""
if self.filterset_class:
return self.filterset_class
elif self.model:
return filterset_factory(model=self.model, fields=self.filterset_fields)
else:
msg = "'%s' must define 'filterset_class' or 'model'"
raise ImproperlyConfigured(msg % self.__class__.__name__)
Source code
in mixins.py
line 28
def get_filterset_class(self):
"""
Get or generate the FilterSet class for this view.
This method checks model_admin configuration and uses FilterSetFactory
to generate an appropriate FilterSet class.
Returns:
FilterSet class, or None if no filters configured
"""
# Check if already cached
if self.filterset_class is not None:
return self.filterset_class
# Generate from ModelAdmin configuration
from .filterset_factory import FilterSetFactory
factory = FilterSetFactory()
filterset_class = factory.create_filterset(model=self.model, model_admin=self.model_admin)
return filterset_class
get_filterset_kwargs(self, filterset_class)
Defined in:
<class 'django_filters.views.FilterMixin'>
Returns the keyword arguments for instantiating the filterset.
Source code
in views.py
line 40
def get_filterset_kwargs(self, filterset_class):
"""
Returns the keyword arguments for instantiating the filterset.
"""
kwargs = {
"data": self.request.GET or None,
"request": self.request,
}
try:
kwargs.update(
{
"queryset": self.get_queryset(),
}
)
except ImproperlyConfigured:
# ignore the error here if the filterset has a model defined
# to acquire a queryset from
if filterset_class._meta.model is None:
msg = (
"'%s' does not define a 'model' and the view '%s' does "
"not return a valid queryset from 'get_queryset'. You "
"must fix one of them."
)
args = (filterset_class.__name__, self.__class__.__name__)
raise ImproperlyConfigured(msg % args)
return kwargs
get_login_url(self)
Defined in:
<class 'django.contrib.auth.mixins.AccessMixin'>
Override this method to override the login_url attribute.
Source code
in mixins.py
line 21
def get_login_url(self):
"""
Override this method to override the login_url attribute.
"""
login_url = self.login_url or settings.LOGIN_URL
if not login_url:
raise ImproperlyConfigured(
f"{self.__class__.__name__} is missing the login_url attribute. Define "
f"{self.__class__.__name__}.login_url, settings.LOGIN_URL, or override "
f"{self.__class__.__name__}.get_login_url()."
)
return str(login_url)
get_object(self, queryset=None)
Defined in:
<class 'djadmin.plugins.permissions.mixins.PermissionMixin'>
Override to check object permissions after fetching.
Source code
in mixins.py
line 39
def get_object(self, queryset=None):
"""Override to check object permissions after fetching."""
obj = super().get_object(queryset)
# Get permission class from action or model_admin
permission_class = self._get_permission_class()
if permission_class is not None:
# Check object permission
if not permission_class.has_object_permission(self, obj):
raise PermissionDenied(f'You do not have permission to access this {obj._meta.verbose_name}.')
return obj
get_ordering(self)
Defined in:
<class 'django.views.generic.list.MultipleObjectMixin'>
Return the field or fields to use for ordering the queryset.
Source code
in list.py
line 49
def get_ordering(self):
"""Return the field or fields to use for ordering the queryset."""
return self.ordering
get_paginate_by(self, queryset)
Defined in:
<class 'django.views.generic.list.MultipleObjectMixin'>
Get the number of items to paginate by, or None for no pagination.
Source code
in list.py
line 81
def get_paginate_by(self, queryset):
"""
Get the number of items to paginate by, or ``None`` for no pagination.
"""
return self.paginate_by
get_paginate_orphans(self)
Defined in:
<class 'django.views.generic.list.MultipleObjectMixin'>
Return the maximum number of orphans extend the last page by when paginating.
Source code
in list.py
line 99
def get_paginate_orphans(self):
"""
Return the maximum number of orphans extend the last page by when
paginating.
"""
return self.paginate_orphans
get_paginator(self, queryset, per_page, orphans=0, allow_empty_first_page=True, **kwargs)
Defined in:
<class 'django.views.generic.list.MultipleObjectMixin'>
Return an instance of the paginator for this view.
Source code
in list.py
line 87
def get_paginator(
self, queryset, per_page, orphans=0, allow_empty_first_page=True, **kwargs
):
"""Return an instance of the paginator for this view."""
return self.paginator_class(
queryset,
per_page,
orphans=orphans,
allow_empty_first_page=allow_empty_first_page,
**kwargs,
)
get_permission_denied_message(self)
Defined in:
<class 'django.contrib.auth.mixins.AccessMixin'>
Override this method to override the permission_denied_message attribute.
Source code
in mixins.py
line 34
def get_permission_denied_message(self):
"""
Override this method to override the permission_denied_message attribute.
"""
return self.permission_denied_message
get_queryset(self)
Defined in:
<class 'django.views.generic.list.MultipleObjectMixin'>
Return the list of items for this view.
The return value must be an iterable and may be an instance of
QuerySet in which case QuerySet specific behavior will be enabled.
Source code
in actions.py
line 195
def get_queryset(self):
"""
Get queryset for list view with ordering and plugin modifications.
When this method is copied to the view class, 'self' will be the view instance.
The view has model_admin, request, etc. as attributes.
Returns:
QuerySet for the model
"""
from djadmin.plugins import pm
# Call super to get base queryset from ListView
# Use type(self).__mro__[1] to get the parent class in the view's MRO
# This works because when copied to the view, self is the view instance
queryset = super(type(self), self).get_queryset()
# Apply ordering from model_admin (view has this as an attribute)
if hasattr(self, 'ordering') and self.ordering:
queryset = queryset.order_by(*self.ordering)
# Allow plugins to modify queryset
plugin_results = pm.hook.djadmin_modify_queryset(
queryset=queryset,
request=self.request,
view=self,
)
# Use the last non-None result
for result in reversed(plugin_results):
if result is not None:
queryset = result
break
return queryset
Source code
in mixins.py
line 584
def get_queryset(self):
"""
Get the queryset with search applied.
This overrides ListView's get_queryset() to apply search filtering.
Returns:
Filtered QuerySet
"""
# Get base queryset from parent
queryset = super().get_queryset()
# Apply search if configured
return self.apply_search(queryset)
Source code
in mixins.py
line 87
def get_queryset(self):
"""
Get the filtered queryset for the ListView.
This overrides ListView's get_queryset() to apply filtering and ordering.
Returns:
Filtered QuerySet
"""
# Get the FilterSet class
filterset_class = self.get_filterset_class()
if filterset_class is None:
# No filters configured, just apply ordering
queryset = self.get_queryset_for_filter()
return self._apply_ordering(queryset)
# Get the FilterSet instance
self.filterset = self.get_filterset(filterset_class)
if self.filterset is None:
queryset = self.get_queryset_for_filter()
return self._apply_ordering(queryset)
# Apply ordering to filtered queryset
return self._apply_ordering(self.filterset.qs)
Source code
in actions.py
line 195
def get_queryset(self):
"""
Get queryset for list view with ordering and plugin modifications.
When this method is copied to the view class, 'self' will be the view instance.
The view has model_admin, request, etc. as attributes.
Returns:
QuerySet for the model
"""
from djadmin.plugins import pm
# Call super to get base queryset from ListView
# Use type(self).__mro__[1] to get the parent class in the view's MRO
# This works because when copied to the view, self is the view instance
queryset = super(type(self), self).get_queryset()
# Apply ordering from model_admin (view has this as an attribute)
if hasattr(self, 'ordering') and self.ordering:
queryset = queryset.order_by(*self.ordering)
# Allow plugins to modify queryset
plugin_results = pm.hook.djadmin_modify_queryset(
queryset=queryset,
request=self.request,
view=self,
)
# Use the last non-None result
for result in reversed(plugin_results):
if result is not None:
queryset = result
break
return queryset
get_queryset_for_filter(self)
Defined in:
<class 'djadmin_filters.mixins.DjAdminFiltersMixin'>
Get the base queryset to be filtered.
This method gets the queryset before filtering is applied, allowing parent classes to modify it first.
Returns: QuerySet to be filtered
Source code
in mixins.py
line 69
def get_queryset_for_filter(self):
"""
Get the base queryset to be filtered.
This method gets the queryset before filtering is applied,
allowing parent classes to modify it first.
Returns:
QuerySet to be filtered
"""
# Call super to get the base queryset with any modifications
# from other mixins or the action
if hasattr(super(), 'get_queryset'):
return super().get_queryset()
# Fallback to model's default manager
return self.model._default_manager.all()
get_redirect_field_name(self)
Defined in:
<class 'django.contrib.auth.mixins.AccessMixin'>
Override this method to override the redirect_field_name attribute.
Source code
in mixins.py
line 40
def get_redirect_field_name(self):
"""
Override this method to override the redirect_field_name attribute.
"""
return self.redirect_field_name
get_search_fields(self)
Defined in:
<class 'djadmin.plugins.core.mixins.SearchMixin'>
Get the list of fields to search.
Returns: List of field names from model_admin.search_fields, or empty list
Source code
in mixins.py
line 466
def get_search_fields(self):
"""
Get the list of fields to search.
Returns:
List of field names from model_admin.search_fields, or empty list
"""
return getattr(self.model_admin, 'search_fields', None) or []
get_search_query(self)
Defined in:
<class 'djadmin.plugins.core.mixins.SearchMixin'>
Get the search query from request parameters.
Returns: String search query or None
Source code
in mixins.py
line 457
def get_search_query(self):
"""
Get the search query from request parameters.
Returns:
String search query or None
"""
return self.request.GET.get('search', '').strip()
get_strict(self)
Defined in:
<class 'django_filters.views.FilterMixin'>
Source code
in views.py
line 67
def get_strict(self):
return self.strict
get_template_names(self)
Defined in:
<class 'django.views.generic.base.TemplateResponseMixin'>
Return a list of template names to be used for the request. Must return a list. May not be called if render_to_response() is overridden.
Source code
in actions.py
line 175
def get_template_names(self):
"""
Get template names as a list (Django CBV expects plural method).
This wraps get_template_name() and ensures the result is a list.
Returns:
List of template path strings
"""
template_names = []
if model_name := getattr(getattr(self.model, '_meta', None), 'model_name', None):
template_names.append(f'djadmin/{self.model._meta.app_label}/{model_name}_{self.action.action_name}.html')
template_names.append(f'djadmin/actions/{self.action.action_name}.html')
return template_names
Source code
in list.py
line 187
def get_template_names(self):
"""
Return a list of template names to be used for the request. Must return
a list. May not be called if render_to_response is overridden.
"""
try:
names = super().get_template_names()
except ImproperlyConfigured:
# If template_name isn't specified, it's not a problem --
# we just start with an empty list.
names = []
# If the list is a queryset, we'll invent a template name based on the
# app and model name. This name gets put at the end of the template
# name list so that user-supplied names override the automatically-
# generated ones.
if hasattr(self.object_list, "model"):
opts = self.object_list.model._meta
names.append(
"%s/%s%s.html"
% (opts.app_label, opts.model_name, self.template_name_suffix)
)
elif not names:
raise ImproperlyConfigured(
"%(cls)s requires either a 'template_name' attribute "
"or a get_queryset() method that returns a QuerySet."
% {
"cls": self.__class__.__name__,
}
)
return names
Source code
in base.py
line 175
def get_template_names(self):
"""
Get template names as a list (Django CBV expects plural method).
This wraps get_template_name() and ensures the result is a list.
Returns:
List of template path strings
"""
template_names = []
if model_name := getattr(getattr(self.model, '_meta', None), 'model_name', None):
template_names.append(f'djadmin/{self.model._meta.app_label}/{model_name}_{self.action.action_name}.html')
template_names.append(f'djadmin/actions/{self.action.action_name}.html')
return template_names
get_test_func(self)
Defined in:
<class 'django.contrib.auth.mixins.UserPassesTestMixin'>
Override this method to use a different test_func method.
Source code
in mixins.py
line 125
def get_test_func(self):
"""
Override this method to use a different test_func method.
"""
return self.test_func
handle_no_permission(self)
Defined in:
<class 'django.contrib.auth.mixins.AccessMixin'>
Source code
in mixins.py
line 46
def handle_no_permission(self):
if self.raise_exception or self.request.user.is_authenticated:
raise PermissionDenied(self.get_permission_denied_message())
path = self.request.build_absolute_uri()
resolved_login_url = resolve_url(self.get_login_url())
# If the login url is the same scheme and net location then use the
# path as the "next" url.
login_scheme, login_netloc = urlsplit(resolved_login_url)[:2]
current_scheme, current_netloc = urlsplit(path)[:2]
if (not login_scheme or login_scheme == current_scheme) and (
not login_netloc or login_netloc == current_netloc
):
path = self.request.get_full_path()
return redirect_to_login(
path,
resolved_login_url,
self.get_redirect_field_name(),
)
http_method_not_allowed(self, request, *args, **kwargs)
Defined in:
<class 'django.views.generic.base.View'>
Source code
in base.py
line 146
def http_method_not_allowed(self, request, *args, **kwargs):
response = HttpResponseNotAllowed(self._allowed_methods())
log_response(
"Method Not Allowed (%s): %s",
request.method,
request.path,
response=response,
request=request,
)
if self.view_is_async:
async def func():
return response
return func()
else:
return response
options(self, request, *args, **kwargs)
Defined in:
<class 'django.views.generic.base.View'>
Handle responding to requests for the OPTIONS HTTP verb.
Source code
in base.py
line 165
def options(self, request, *args, **kwargs):
"""Handle responding to requests for the OPTIONS HTTP verb."""
response = HttpResponse()
response.headers["Allow"] = ", ".join(self._allowed_methods())
response.headers["Content-Length"] = "0"
if self.view_is_async:
async def func():
return response
return func()
else:
return response
paginate_queryset(self, queryset, page_size)
Defined in:
<class 'django.views.generic.list.MultipleObjectMixin'>
Paginate the queryset, if needed.
Source code
in list.py
line 53
def paginate_queryset(self, queryset, page_size):
"""Paginate the queryset, if needed."""
paginator = self.get_paginator(
queryset,
page_size,
orphans=self.get_paginate_orphans(),
allow_empty_first_page=self.get_allow_empty(),
)
page_kwarg = self.page_kwarg
page = self.kwargs.get(page_kwarg) or self.request.GET.get(page_kwarg) or 1
try:
page_number = int(page)
except ValueError:
if page == "last":
page_number = paginator.num_pages
else:
raise Http404(
_("Page is not “last”, nor can it be converted to an int.")
)
try:
page = paginator.page(page_number)
return (paginator, page, page.object_list, page.has_other_pages())
except InvalidPage as e:
raise Http404(
_("Invalid page (%(page_number)s): %(message)s")
% {"page_number": page_number, "message": str(e)}
)
render_to_response(self, context, **response_kwargs)
Defined in:
<class 'django.views.generic.base.TemplateResponseMixin'>
Return a response, using the response_class for this view, with a
template rendered with the given context.
Pass response_kwargs to the constructor of the response class.
Source code
in base.py
line 192
def render_to_response(self, context, **response_kwargs):
"""
Return a response, using the `response_class` for this view, with a
template rendered with the given context.
Pass response_kwargs to the constructor of the response class.
"""
response_kwargs.setdefault("content_type", self.content_type)
return self.response_class(
request=self.request,
template=self.get_template_names(),
context=context,
using=self.template_engine,
**response_kwargs,
)
setup(self, request, *args, **kwargs)
Defined in:
<class 'django.views.generic.base.View'>
Initialize attributes shared by all view methods.
Source code
in base.py
line 126
def setup(self, request, *args, **kwargs):
"""Initialize attributes shared by all view methods."""
if hasattr(self, "get") and not hasattr(self, "head"):
self.head = self.get
self.request = request
self.args = args
self.kwargs = kwargs
test_func(self)
Defined in:
<class 'django.contrib.auth.mixins.UserPassesTestMixin'>
Source code
in mixins.py
line 118
def test_func(self):
raise NotImplementedError(
"{} is missing the implementation of the test_func() method.".format(
self.__class__.__name__
)
)
Source code
in mixins.py
line 16
def test_func(self):
"""
Permission check method for UserPassesTestMixin.
This method is called by UserPassesTestMixin to check if the user
has permission to access the view.
Returns:
bool: True if user has permission, False otherwise
"""
# Get permission from action or model_admin
perm = self._get_permission_class()
if perm is None:
# None means no permission enforcement (allow all access)
# This happens when:
# 1. Explicitly set to None on ModelAdmin or Action
# 2. No model_admin exists (site-level views like DashboardAction)
return True
# Execute permission with view (self is the view)
return perm(self)
Fields ¶
| Field | Type | Related To |
|---|---|---|
__dict__ |
getset_descriptor |
- |
__weakref__ |
getset_descriptor |
- |