content: from datetime import datetime
  from django.contrib import messages
  from django.contrib.auth.mixins import LoginRequiredMixin
  from django.contrib.contenttypes.models import ContentType
  from django.core.paginator import EmptyPage
  from django.db.models import Count, Q
  from django.http import HttpResponseBadRequest, HttpResponseForbidden, HttpResponse, Http404
  from django.shortcuts import get_object_or_404, redirect, render
  from django.urls import reverse
  from django.utils import timezone
  from django.utils.module_loading import import_string
  from django.utils.translation import gettext as _
  from django.views.generic import View
  from jinja2.exceptions import TemplateError
  
  from core.choices import ManagedFileRootPathChoices
  from core.models import Job
  from core.object_actions import BulkSync
  from dcim.models import Device, DeviceRole, Platform
  from extras.choices import LogLevelChoices
  from extras.dashboard.forms import DashboardWidgetAddForm, DashboardWidgetForm
  from extras.dashboard.utils import get_widget_class
  from extras.utils import SharedObjectViewMixin
  from netbox.object_actions import *
  from netbox.views import generic
  from netbox.views.generic.mixins import TableMixin
  from utilities.forms import ConfirmationForm, get_field_value
  from utilities.htmx import htmx_partial, htmx_maybe_redirect_current_page
  from utilities.paginator import EnhancedPaginator, get_paginate_count
  from utilities.query import count_related
  from utilities.querydict import normalize_querydict
  from utilities.request import copy_safe_request
  from utilities.rqworker import get_workers_for_queue
  from utilities.templatetags.builtins.filters import render_markdown
  from utilities.views import ContentTypePermissionRequiredMixin, get_action_url, register_model_view
  from virtualization.models import VirtualMachine
  from . import filtersets, forms, tables
  from .constants import LOG_LEVEL_RANK
  from .models import *
  from .tables import ReportResultsTable, ScriptResultsTable, ScriptJobTable
  
  
  #
  # Custom fields
  #
  
  @register_model_view(CustomField, 'list', path='', detail=False)
  class CustomFieldListView(generic.ObjectListView):
      queryset = CustomField.objects.select_related('choice_set')
      filterset = filtersets.CustomFieldFilterSet
      filterset_form = forms.CustomFieldFilterForm
      table = tables.CustomFieldTable
  
  
  @register_model_view(CustomField)
  class CustomFieldView(generic.ObjectView):
      queryset = CustomField.objects.select_related('choice_set')
  
      def get_extra_context(self, request, instance):
          related_models = ()
  
          for object_type in instance.object_types.all():
              related_models += (
                  object_type.model_class().objects.restrict(request.user, 'view').exclude(
                      Q(**{f'custom_field_data__{instance.name}': ''}) |
                      Q(**{f'custom_field_data__{instance.name}': None})
                  ),
              )
  
          return {
              'related_models': related_models
          }
  
  
  @register_model_view(CustomField, 'add', detail=False)
  @register_model_view(CustomField, 'edit')
  class CustomFieldEditView(generic.ObjectEditView):
      queryset = CustomField.objects.select_related('choice_set')
      form = forms.CustomFieldForm
  
  
  @register_model_view(CustomField, 'delete')
  class CustomFieldDeleteView(generic.ObjectDeleteView):
      queryset = CustomField.objects.select_related('choice_set')
  
  
  @register_model_view(CustomField, 'bulk_import', path='import', detail=False)
  class CustomFieldBulkImportView(generic.BulkImportView):
      queryset = CustomField.objects.select_related('choice_set')
      model_form = forms.CustomFieldImportForm
  
  
  @register_model_view(CustomField, 'bulk_edit', path='edit', detail=False)
  class CustomFieldBulkEditView(generic.BulkEditView):
      queryset = CustomField.objects.select_related('choice_set')
      filterset = filtersets.CustomFieldFilterSet
      table = tables.CustomFieldTable
      form = forms.CustomFieldBulkEditForm
  
  
  @register_model_view(CustomField, 'bulk_rename', path='rename', detail=False)
  class CustomFieldBulkRenameView(generic.BulkRenameView):
      queryset = CustomField.objects.all()
      filterset = filtersets.CustomFieldFilterSet
  
  
  @register_model_view(CustomField, 'bulk_delete', path='delete', detail=False)
  class CustomFieldBulkDeleteView(generic.BulkDeleteView):
      queryset = CustomField.objects.select_related('choice_set')
      filterset = filtersets.CustomFieldFilterSet
      table = tables.CustomFieldTable
  
  
  #
  # Custom field choices
  #
  
  @register_model_view(CustomFieldChoiceSet, 'list', path='', detail=False)
  class CustomFieldChoiceSetListView(generic.ObjectListView):
      queryset = CustomFieldChoiceSet.objects.all()
      filterset = filtersets.CustomFieldChoiceSetFilterSet
      filterset_form = forms.CustomFieldChoiceSetFilterForm
      table = tables.CustomFieldChoiceSetTable
  
  
  @register_model_view(CustomFieldChoiceSet)
  class CustomFieldChoiceSetView(generic.ObjectView):
      queryset = CustomFieldChoiceSet.objects.all()
  
      def get_extra_context(self, request, instance):
  
          # Paginate choices list
          per_page = get_paginate_count(request)
          try:
              page_number = request.GET.get('page', 1)
          except ValueError:
              page_number = 1
          paginator = EnhancedPaginator(instance.choices, per_page)
          try:
              choices = paginator.page(page_number)
          except EmptyPage:
              choices = paginator.page(paginator.num_pages)
  
          return {
              'paginator': paginator,
              'choices': choices,
          }
  
  
  @register_model_view(CustomFieldChoiceSet, 'add', detail=False)
  @register_model_view(CustomFieldChoiceSet, 'edit')
  class CustomFieldChoiceSetEditView(generic.ObjectEditView):
      queryset = CustomFieldChoiceSet.objects.all()
      form = forms.CustomFieldChoiceSetForm
  
  
  @register_model_view(CustomFieldChoiceSet, 'delete')
  class CustomFieldChoiceSetDeleteView(generic.ObjectDeleteView):
      queryset = CustomFieldChoiceSet.objects.all()
  
  
  @register_model_view(CustomFieldChoiceSet, 'bulk_import', path='import', detail=False)
  class CustomFieldChoiceSetBulkImportView(generic.BulkImportView):
      queryset = CustomFieldChoiceSet.objects.all()
      model_form = forms.CustomFieldChoiceSetImportForm
  
  
  @register_model_view(CustomFieldChoiceSet, 'bulk_edit', path='edit', detail=False)
  class CustomFieldChoiceSetBulkEditView(generic.BulkEditView):
      queryset = CustomFieldChoiceSet.objects.all()
      filterset = filtersets.CustomFieldChoiceSetFilterSet
      table = tables.CustomFieldChoiceSetTable
      form = forms.CustomFieldChoiceSetBulkEditForm
  
  
  @register_model_view(CustomFieldChoiceSet, 'bulk_rename', path='rename', detail=False)
  class CustomFieldChoiceSetBulkRenameView(generic.BulkRenameView):
      queryset = CustomFieldChoiceSet.objects.all()
      filterset = filtersets.CustomFieldChoiceSetFilterSet
  
  
  @register_model_view(CustomFieldChoiceSet, 'bulk_delete', path='delete', detail=False)
  class CustomFieldChoiceSetBulkDeleteView(generic.BulkDeleteView):
      queryset = CustomFieldChoiceSet.objects.all()
      filterset = filtersets.CustomFieldChoiceSetFilterSet
      table = tables.CustomFieldChoiceSetTable
  
  
  #
  # Custom links
  #
  
  @register_model_view(CustomLink, 'list', path='', detail=False)
  class CustomLinkListView(generic.ObjectListView):
      queryset = CustomLink.objects.all()
      filterset = filtersets.CustomLinkFilterSet
      filterset_form = forms.CustomLinkFilterForm
      table = tables.CustomLinkTable
  
  
  @register_model_view(CustomLink)
  class CustomLinkView(generic.ObjectView):
      queryset = CustomLink.objects.all()
  
  
  @register_model_view(CustomLink, 'add', detail=False)
  @register_model_view(CustomLink, 'edit')
  class CustomLinkEditView(generic.ObjectEditView):
      queryset = CustomLink.objects.all()
      form = forms.CustomLinkForm
  
  
  @register_model_view(CustomLink, 'delete')
  class CustomLinkDeleteView(generic.ObjectDeleteView):
      queryset = CustomLink.objects.all()
  
  
  @register_model_view(CustomLink, 'bulk_import', path='import', detail=False)
  class CustomLinkBulkImportView(generic.BulkImportView):
      queryset = CustomLink.objects.all()
      model_form = forms.CustomLinkImportForm
  
  
  @register_model_view(CustomLink, 'bulk_edit', path='edit', detail=False)
  class CustomLinkBulkEditView(generic.BulkEditView):
      queryset = CustomLink.objects.all()
      filterset = filtersets.CustomLinkFilterSet
      table = tables.CustomLinkTable
      form = forms.CustomLinkBulkEditForm
  
  
  @register_model_view(CustomLink, 'bulk_rename', path='rename', detail=False)
  class CustomLinkBulkRenameView(generic.BulkRenameView):
      queryset = CustomLink.objects.all()
      filterset = filtersets.CustomLinkFilterSet
  
  
  @register_model_view(CustomLink, 'bulk_delete', path='delete', detail=False)
  class CustomLinkBulkDeleteView(generic.BulkDeleteView):
      queryset = CustomLink.objects.all()
      filterset = filtersets.CustomLinkFilterSet
      table = tables.CustomLinkTable
  
  
  #
  # Export templates
  #
  
  @register_model_view(ExportTemplate, 'list', path='', detail=False)
  class ExportTemplateListView(generic.ObjectListView):
      queryset = ExportTemplate.objects.all()
      filterset = filtersets.ExportTemplateFilterSet
      filterset_form = forms.ExportTemplateFilterForm
      table = tables.ExportTemplateTable
      actions = (AddObject, BulkImport, BulkSync, BulkExport, BulkEdit, BulkRename, BulkDelete)
  
  
  @register_model_view(ExportTemplate)
  class ExportTemplateView(generic.ObjectView):
      queryset = ExportTemplate.objects.all()
  
  
  @register_model_view(ExportTemplate, 'add', detail=False)
  @register_model_view(ExportTemplate, 'edit')
  class ExportTemplateEditView(generic.ObjectEditView):
      queryset = ExportTemplate.objects.all()
      form = forms.ExportTemplateForm
  
  
  @register_model_view(ExportTemplate, 'delete')
  class ExportTemplateDeleteView(generic.ObjectDeleteView):
      queryset = ExportTemplate.objects.all()
  
  
  @register_model_view(ExportTemplate, 'bulk_import', path='import', detail=False)
  class ExportTemplateBulkImportView(generic.BulkImportView):
      queryset = ExportTemplate.objects.all()
      model_form = forms.ExportTemplateImportForm
  
  
  @register_model_view(ExportTemplate, 'bulk_edit', path='edit', detail=False)
  class ExportTemplateBulkEditView(generic.BulkEditView):
      queryset = ExportTemplate.objects.all()
      filterset = filtersets.ExportTemplateFilterSet
      table = tables.ExportTemplateTable
      form = forms.ExportTemplateBulkEditForm
  
  
  @register_model_view(ExportTemplate, 'bulk_rename', path='rename', detail=False)
  class ExportTemplateBulkRenameView(generic.BulkRenameView):
      queryset = ExportTemplate.objects.all()
      filterset = filtersets.ExportTemplateFilterSet
  
  
  @register_model_view(ExportTemplate, 'bulk_delete', path='delete', detail=False)
  class ExportTemplateBulkDeleteView(generic.BulkDeleteView):
      queryset = ExportTemplate.objects.all()
      filterset = filtersets.ExportTemplateFilterSet
      table = tables.ExportTemplateTable
  
  
  @register_model_view(ExportTemplate, 'bulk_sync', path='sync', detail=False)
  class ExportTemplateBulkSyncDataView(generic.BulkSyncDataView):
      queryset = ExportTemplate.objects.all()
  
  
  #
  # Saved filters
  #
  
  @register_model_view(SavedFilter, 'list', path='', detail=False)
  class SavedFilterListView(SharedObjectViewMixin, generic.ObjectListView):
      queryset = SavedFilter.objects.all()
      filterset = filtersets.SavedFilterFilterSet
      filterset_form = forms.SavedFilterFilterForm
      table = tables.SavedFilterTable
  
  
  @register_model_view(SavedFilter)
  class SavedFilterView(SharedObjectViewMixin, generic.ObjectView):
      queryset = SavedFilter.objects.all()
  
  
  @register_model_view(SavedFilter, 'add', detail=False)
  @register_model_view(SavedFilter, 'edit')
  class SavedFilterEditView(SharedObjectViewMixin, generic.ObjectEditView):
      queryset = SavedFilter.objects.all()
      form = forms.SavedFilterForm
  
      def alter_object(self, obj, request, url_args, url_kwargs):
          if not obj.pk:
              obj.user = request.user
          return obj
  
  
  @register_model_view(SavedFilter, 'delete')
  class SavedFilterDeleteView(SharedObjectViewMixin, generic.ObjectDeleteView):
      queryset = SavedFilter.objects.all()
  
  
  @register_model_view(SavedFilter, 'bulk_import', path='import', detail=False)
  class SavedFilterBulkImportView(SharedObjectViewMixin, generic.BulkImportView):
      queryset = SavedFilter.objects.all()
      model_form = forms.SavedFilterImportForm
  
  
  @register_model_view(SavedFilter, 'bulk_edit', path='edit', detail=False)
  class SavedFilterBulkEditView(SharedObjectViewMixin, generic.BulkEditView):
      queryset = SavedFilter.objects.all()
      filterset = filtersets.SavedFilterFilterSet
      table = tables.SavedFilterTable
      form = forms.SavedFilterBulkEditForm
  
  
  @register_model_view(SavedFilter, 'bulk_rename', path='rename', detail=False)
  class SavedFilterBulkRenameView(generic.BulkRenameView):
      queryset = SavedFilter.objects.all()
      filterset = filtersets.SavedFilterFilterSet
  
  
  @register_model_view(SavedFilter, 'bulk_delete', path='delete', detail=False)
  class SavedFilterBulkDeleteView(SharedObjectViewMixin, generic.BulkDeleteView):
      queryset = SavedFilter.objects.all()
      filterset = filtersets.SavedFilterFilterSet
      table = tables.SavedFilterTable
  
  
  #
  # Table configs
  #
  
  @register_model_view(TableConfig, 'list', path='', detail=False)
  class TableConfigListView(SharedObjectViewMixin, generic.ObjectListView):
      queryset = TableConfig.objects.all()
      filterset = filtersets.TableConfigFilterSet
      filterset_form = forms.TableConfigFilterForm
      table = tables.TableConfigTable
      actions = (BulkExport, BulkEdit, BulkRename, BulkDelete)
  
  
  @register_model_view(TableConfig)
  class TableConfigView(SharedObjectViewMixin, generic.ObjectView):
      queryset = TableConfig.objects.all()
  
      def get_extra_context(self, request, instance):
          table = instance.table_class([])
          return {
              'columns': dict(table.columns.items()),
          }
  
  
  @register_model_view(TableConfig, 'add', detail=False)
  @register_model_view(TableConfig, 'edit')
  class TableConfigEditView(SharedObjectViewMixin, generic.ObjectEditView):
      queryset = TableConfig.objects.all()
      form = forms.TableConfigForm
      template_name = 'extras/tableconfig_edit.html'
  
      def alter_object(self, obj, request, url_args, url_kwargs):
          if not obj.pk:
              obj.user = request.user
          return obj
  
  
  @register_model_view(TableConfig, 'delete')
  class TableConfigDeleteView(SharedObjectViewMixin, generic.ObjectDeleteView):
      queryset = TableConfig.objects.all()
  
  
  @register_model_view(TableConfig, 'bulk_edit', path='edit', detail=False)
  class TableConfigBulkEditView(SharedObjectViewMixin, generic.BulkEditView):
      queryset = TableConfig.objects.all()
      filterset = filtersets.TableConfigFilterSet
      table = tables.TableConfigTable
      form = forms.TableConfigBulkEditForm
  
  
  @register_model_view(TableConfig, 'bulk_rename', path='rename', detail=False)
  class TableConfigBulkRenameView(generic.BulkRenameView):
      queryset = TableConfig.objects.all()
      filterset = filtersets.TableConfigFilterSet
  
  
  @register_model_view(TableConfig, 'bulk_delete', path='delete', detail=False)
  class TableConfigBulkDeleteView(SharedObjectViewMixin, generic.BulkDeleteView):
      queryset = TableConfig.objects.all()
      filterset = filtersets.TableConfigFilterSet
      table = tables.TableConfigTable
  
  
  #
  # Bookmarks
  #
  
  @register_model_view(Bookmark, 'add', detail=False)
  class BookmarkCreateView(generic.ObjectEditView):
      form = forms.BookmarkForm
  
      def get_queryset(self, request):
          return Bookmark.objects.filter(user=request.user)
  
      def alter_object(self, obj, request, url_args, url_kwargs):
          obj.user = request.user
          return obj
  
  
  @register_model_view(Bookmark, 'delete')
  class BookmarkDeleteView(generic.ObjectDeleteView):
  
      def get_queryset(self, request):
          return Bookmark.objects.filter(user=request.user)
  
  
  @register_model_view(Bookmark, 'bulk_delete', path='delete', detail=False)
  class BookmarkBulkDeleteView(generic.BulkDeleteView):
      table = tables.BookmarkTable
  
      def get_queryset(self, request):
          return Bookmark.objects.filter(user=request.user)
  
  
  #
  # Notification groups
  #
  
  @register_model_view(NotificationGroup, 'list', path='', detail=False)
  class NotificationGroupListView(generic.ObjectListView):
      queryset = NotificationGroup.objects.all()
      filterset = filtersets.NotificationGroupFilterSet
      filterset_form = forms.NotificationGroupFilterForm
      table = tables.NotificationGroupTable
  
  
  @register_model_view(NotificationGroup)
  class NotificationGroupView(generic.ObjectView):
      queryset = NotificationGroup.objects.all()
  
  
  @register_model_view(NotificationGroup, 'add', detail=False)
  @register_model_view(NotificationGroup, 'edit')
  class NotificationGroupEditView(generic.ObjectEditView):
      queryset = NotificationGroup.objects.all()
      form = forms.NotificationGroupForm
  
  
  @register_model_view(NotificationGroup, 'delete')
  class NotificationGroupDeleteView(generic.ObjectDeleteView):
      queryset = NotificationGroup.objects.all()
  
  
  @register_model_view(NotificationGroup, 'bulk_import', path='import', detail=False)
  class NotificationGroupBulkImportView(generic.BulkImportView):
      queryset = NotificationGroup.objects.all()
      model_form = forms.NotificationGroupImportForm
  
  
  @register_model_view(NotificationGroup, 'bulk_edit', path='edit', detail=False)
  class NotificationGroupBulkEditView(generic.BulkEditView):
      queryset = NotificationGroup.objects.all()
      filterset = filtersets.NotificationGroupFilterSet
      table = tables.NotificationGroupTable
      form = forms.NotificationGroupBulkEditForm
  
  
  @register_model_view(NotificationGroup, 'bulk_rename', path='rename', detail=False)
  class NotificationGroupBulkRenameView(generic.BulkRenameView):
      queryset = NotificationGroup.objects.all()
      filterset = filtersets.NotificationGroupFilterSet
  
  
  @register_model_view(NotificationGroup, 'bulk_delete', path='delete', detail=False)
  class NotificationGroupBulkDeleteView(generic.BulkDeleteView):
      queryset = NotificationGroup.objects.all()
      filterset = filtersets.NotificationGroupFilterSet
      table = tables.NotificationGroupTable
  
  
  #
  # Notifications
  #
  
  class NotificationsView(LoginRequiredMixin, View):
      """
      HTMX-only user-specific notifications list.
      """
      def get(self, request):
          return render(request, 'htmx/notifications.html', {
              'notifications': request.user.notifications.unread()[:10],
              'total_count': request.user.notifications.count(),
              'unread_count': request.user.notifications.unread().count(),
          })
  
  
  @register_model_view(Notification, 'read')
  class NotificationReadView(LoginRequiredMixin, View):
      """
      Mark the Notification read and redirect the user to its attached object.
      """
  
      def get(self, request, pk):
          # Mark the Notification as read
          notification = get_object_or_404(request.user.notifications, pk=pk)
          notification.read = timezone.now()
          notification.save()
  
          # Redirect to the object if it has a URL (deleted objects will not)
          if hasattr(notification.object, 'get_absolute_url'):
              return redirect(notification.object.get_absolute_url())
  
          return redirect('account:notifications')
  
  
  @register_model_view(Notification, name='dismiss_all', path='dismiss-all', detail=False)
  class NotificationDismissAllView(LoginRequiredMixin, View):
      """
      Convenience view to clear all *unread* notifications for the current user.
      """
  
      def get(self, request):
          request.user.notifications.unread().delete()
          if htmx_partial(request):
              # If a user is currently on the notification page, redirect there (full repaint)
              redirect_resp = htmx_maybe_redirect_current_page(request, 'account:notifications', preserve_query=True)
              if redirect_resp:
                  return redirect_resp
  
              return render(request, 'htmx/notifications.html', {
                  'notifications': request.user.notifications.unread()[:10],
                  'total_count': request.user.notifications.count(),
                  'unread_count': request.user.notifications.unread().count(),
              })
          return redirect('account:notifications')
  
  
  @register_model_view(Notification, 'dismiss')
  class NotificationDismissView(LoginRequiredMixin, View):
      """
      A convenience view which allows deleting notifications with one click.
      """
  
      def get(self, request, pk):
          notification = get_object_or_404(request.user.notifications, pk=pk)
          notification.delete()
  
          if htmx_partial(request):
              # If a user is currently on the notification page, redirect there (full repaint)
              redirect_resp = htmx_maybe_redirect_current_page(request, 'account:notifications', preserve_query=True)
              if redirect_resp:
                  return redirect_resp
  
              return render(request, 'htmx/notifications.html', {
                  'notifications': request.user.notifications.unread()[:10],
                  'total_count': request.user.notifications.count(),
                  'unread_count': request.user.notifications.unread().count(),
              })
  
          return redirect('account:notifications')
  
  
  @register_model_view(Notification, 'delete')
  class NotificationDeleteView(generic.ObjectDeleteView):
  
      def get_queryset(self, request):
          return Notification.objects.filter(user=request.user)
  
  
  @register_model_view(Notification, 'bulk_delete', path='delete', detail=False)
  class NotificationBulkDeleteView(generic.BulkDeleteView):
      table = tables.NotificationTable
  
      def get_queryset(self, request):
          return Notification.objects.filter(user=request.user)
  
  
  #
  # Subscriptions
  #
  
  @register_model_view(Subscription, 'add', detail=False)
  class SubscriptionCreateView(generic.ObjectEditView):
      form = forms.SubscriptionForm
  
      def get_queryset(self, request):
          return Subscription.objects.filter(user=request.user)
  
      def alter_object(self, obj, request, url_args, url_kwargs):
          obj.user = request.user
          return obj
  
  
  @register_model_view(Subscription, 'delete')
  class SubscriptionDeleteView(generic.ObjectDeleteView):
  
      def get_queryset(self, request):
          return Subscription.objects.filter(user=request.user)
  
  
  @register_model_view(Subscription, 'bulk_delete', path='delete', detail=False)
  class SubscriptionBulkDeleteView(generic.BulkDeleteView):
      table = tables.SubscriptionTable
  
      def get_queryset(self, request):
          return Subscription.objects.filter(user=request.user)
  
  
  #
  # Webhooks
  #
  
  @register_model_view(Webhook, 'list', path='', detail=False)
  class WebhookListView(generic.ObjectListView):
      queryset = Webhook.objects.all()
      filterset = filtersets.WebhookFilterSet
      filterset_form = forms.WebhookFilterForm
      table = tables.WebhookTable
  
  
  @register_model_view(Webhook)
  class WebhookView(generic.ObjectView):
      queryset = Webhook.objects.all()
  
  
  @register_model_view(Webhook, 'add', detail=False)
  @register_model_view(Webhook, 'edit')
  class WebhookEditView(generic.ObjectEditView):
      queryset = Webhook.objects.all()
      form = forms.WebhookForm
  
  
  @register_model_view(Webhook, 'delete')
  class WebhookDeleteView(generic.ObjectDeleteView):
      queryset = Webhook.objects.all()
  
  
  @register_model_view(Webhook, 'bulk_import', path='import', detail=False)
  class WebhookBulkImportView(generic.BulkImportView):
      queryset = Webhook.objects.all()
      model_form = forms.WebhookImportForm
  
  
  @register_model_view(Webhook, 'bulk_edit', path='edit', detail=False)
  class WebhookBulkEditView(generic.BulkEditView):
      queryset = Webhook.objects.all()
      filterset = filtersets.WebhookFilterSet
      table = tables.WebhookTable
      form = forms.WebhookBulkEditForm
  
  
  @register_model_view(Webhook, 'bulk_rename', path='rename', detail=False)
  class WebhookBulkRenameView(generic.BulkRenameView):
      queryset = Webhook.objects.all()
      filterset = filtersets.WebhookFilterSet
  
  
  @register_model_view(Webhook, 'bulk_delete', path='delete', detail=False)
  class WebhookBulkDeleteView(generic.BulkDeleteView):
      queryset = Webhook.objects.all()
      filterset = filtersets.WebhookFilterSet
      table = tables.WebhookTable
  
  
  #
  # Event Rules
  #
  
  @register_model_view(EventRule, 'list', path='', detail=False)
  class EventRuleListView(generic.ObjectListView):
      queryset = EventRule.objects.all()
      filterset = filtersets.EventRuleFilterSet
      filterset_form = forms.EventRuleFilterForm
      table = tables.EventRuleTable
  
  
  @register_model_view(EventRule)
  class EventRuleView(generic.ObjectView):
      queryset = EventRule.objects.all()
  
  
  @register_model_view(EventRule, 'add', detail=False)
  @register_model_view(EventRule, 'edit')
  class EventRuleEditView(generic.ObjectEditView):
      queryset = EventRule.objects.all()
      form = forms.EventRuleForm
  
  
  @register_model_view(EventRule, 'delete')
  class EventRuleDeleteView(generic.ObjectDeleteView):
      queryset = EventRule.objects.all()
  
  
  @register_model_view(EventRule, 'bulk_import', path='import', detail=False)
  class EventRuleBulkImportView(generic.BulkImportView):
      queryset = EventRule.objects.all()
      model_form = forms.EventRuleImportForm
  
  
  @register_model_view(EventRule, 'bulk_edit', path='edit', detail=False)
  class EventRuleBulkEditView(generic.BulkEditView):
      queryset = EventRule.objects.all()
      filterset = filtersets.EventRuleFilterSet
      table = tables.EventRuleTable
      form = forms.EventRuleBulkEditForm
  
  
  @register_model_view(EventRule, 'bulk_rename', path='rename', detail=False)
  class EventRuleBulkRenameView(generic.BulkRenameView):
      queryset = EventRule.objects.all()
      filterset = filtersets.EventRuleFilterSet
  
  
  @register_model_view(EventRule, 'bulk_delete', path='delete', detail=False)
  class EventRuleBulkDeleteView(generic.BulkDeleteView):
      queryset = EventRule.objects.all()
      filterset = filtersets.EventRuleFilterSet
      table = tables.EventRuleTable
  
  
  #
  # Tags
  #
  
  @register_model_view(Tag, 'list', path='', detail=False)
  class TagListView(generic.ObjectListView):
      queryset = Tag.objects.annotate(
          items=count_related(TaggedItem, 'tag')
      )
      filterset = filtersets.TagFilterSet
      filterset_form = forms.TagFilterForm
      table = tables.TagTable
  
  
  @register_model_view(Tag)
  class TagView(generic.ObjectView):
      queryset = Tag.objects.all()
  
      def get_extra_context(self, request, instance):
          tagged_items = TaggedItem.objects.filter(tag=instance)
          taggeditem_table = tables.TaggedItemTable(
              data=tagged_items,
              orderable=False
          )
          taggeditem_table.configure(request)
  
          object_types = [
              {
                  'content_type': ContentType.objects.get(pk=ti['content_type']),
                  'item_count': ti['item_count']
              } for ti in tagged_items.values('content_type').annotate(item_count=Count('pk'))
          ]
  
          return {
              'taggeditem_table': taggeditem_table,
              'tagged_item_count': tagged_items.count(),
              'object_types': object_types,
          }
  
  
  @register_model_view(Tag, 'add', detail=False)
  @register_model_view(Tag, 'edit')
  class TagEditView(generic.ObjectEditView):
      queryset = Tag.objects.all()
      form = forms.TagForm
  
  
  @register_model_view(Tag, 'delete')
  class TagDeleteView(generic.ObjectDeleteView):
      queryset = Tag.objects.all()
  
  
  @register_model_view(Tag, 'bulk_import', path='import', detail=False)
  class TagBulkImportView(generic.BulkImportView):
      queryset = Tag.objects.all()
      model_form = forms.TagImportForm
  
  
  @register_model_view(Tag, 'bulk_edit', path='edit', detail=False)
  class TagBulkEditView(generic.BulkEditView):
      queryset = Tag.objects.annotate(
          items=count_related(TaggedItem, 'tag')
      )
      table = tables.TagTable
      form = forms.TagBulkEditForm
  
  
  @register_model_view(Tag, 'bulk_rename', path='rename', detail=False)
  class TagBulkRenameView(generic.BulkRenameView):
      queryset = Tag.objects.all()
  
  
  @register_model_view(Tag, 'bulk_delete', path='delete', detail=False)
  class TagBulkDeleteView(generic.BulkDeleteView):
      queryset = Tag.objects.annotate(
          items=count_related(TaggedItem, 'tag')
      )
      table = tables.TagTable
  
  
  #
  # Config context profiles
  #
  
  @register_model_view(ConfigContextProfile, 'list', path='', detail=False)
  class ConfigContextProfileListView(generic.ObjectListView):
      queryset = ConfigContextProfile.objects.all()
      filterset = filtersets.ConfigContextProfileFilterSet
      filterset_form = forms.ConfigContextProfileFilterForm
      table = tables.ConfigContextProfileTable
      actions = (AddObject, BulkSync, BulkEdit, BulkRename, BulkDelete)
  
  
  @register_model_view(ConfigContextProfile)
  class ConfigContextProfileView(generic.ObjectView):
      queryset = ConfigContextProfile.objects.all()
  
  
  @register_model_view(ConfigContextProfile, 'add', detail=False)
  @register_model_view(ConfigContextProfile, 'edit')
  class ConfigContextProfileEditView(generic.ObjectEditView):
      queryset = ConfigContextProfile.objects.all()
      form = forms.ConfigContextProfileForm
  
  
  @register_model_view(ConfigContextProfile, 'delete')
  class ConfigContextProfileDeleteView(generic.ObjectDeleteView):
      queryset = ConfigContextProfile.objects.all()
  
  
  @register_model_view(ConfigContextProfile, 'bulk_import', path='import', detail=False)
  class ConfigContextProfileBulkImportView(generic.BulkImportView):
      queryset = ConfigContextProfile.objects.all()
      model_form = forms.ConfigContextProfileImportForm
  
  
  @register_model_view(ConfigContextProfile, 'bulk_edit', path='edit', detail=False)
  class ConfigContextProfileBulkEditView(generic.BulkEditView):
      queryset = ConfigContextProfile.objects.all()
      filterset = filtersets.ConfigContextProfileFilterSet
      table = tables.ConfigContextProfileTable
      form = forms.ConfigContextProfileBulkEditForm
  
  
  @register_model_view(ConfigContextProfile, 'bulk_rename', path='rename', detail=False)
  class ConfigContextProfileBulkRenameView(generic.BulkRenameView):
      queryset = ConfigContextProfile.objects.all()
      filterset = filtersets.ConfigContextProfileFilterSet
  
  
  @register_model_view(ConfigContextProfile, 'bulk_delete', path='delete', detail=False)
  class ConfigContextProfileBulkDeleteView(generic.BulkDeleteView):
      queryset = ConfigContextProfile.objects.all()
      filterset = filtersets.ConfigContextProfileFilterSet
      table = tables.ConfigContextProfileTable
  
  
  @register_model_view(ConfigContextProfile, 'bulk_sync', path='sync', detail=False)
  class ConfigContextProfileBulkSyncDataView(generic.BulkSyncDataView):
      queryset = ConfigContextProfile.objects.all()
  
  
  #
  # Config contexts
  #
  
  @register_model_view(ConfigContext, 'list', path='', detail=False)
  class ConfigContextListView(generic.ObjectListView):
      queryset = ConfigContext.objects.all()
      filterset = filtersets.ConfigContextFilterSet
      filterset_form = forms.ConfigContextFilterForm
      table = tables.ConfigContextTable
      actions = (AddObject, BulkSync, BulkEdit, BulkRename, BulkDelete)
  
  
  @register_model_view(ConfigContext)
  class ConfigContextView(generic.ObjectView):
      queryset = ConfigContext.objects.all()
  
      def get_extra_context(self, request, instance):
          # Gather assigned objects for parsing in the template
          assigned_objects = (
              ('Regions', instance.regions.all),
              ('Site Groups', instance.site_groups.all),
              ('Sites', instance.sites.all),
              ('Locations', instance.locations.all),
              ('Device Types', instance.device_types.all),
              ('Roles', instance.roles.all),
              ('Platforms', instance.platforms.all),
              ('Cluster Types', instance.cluster_types.all),
              ('Cluster Groups', instance.cluster_groups.all),
              ('Clusters', instance.clusters.all),
              ('Tenant Groups', instance.tenant_groups.all),
              ('Tenants', instance.tenants.all),
              ('Tags', instance.tags.all),
          )
  
          # Determine user's preferred output format
          if request.GET.get('format') in ['json', 'yaml']:
              format = request.GET.get('format')
              if request.user.is_authenticated:
                  request.user.config.set('data_format', format, commit=True)
          elif request.user.is_authenticated:
              format = request.user.config.get('data_format', 'json')
          else:
              format = 'json'
  
          return {
              'assigned_objects': assigned_objects,
              'format': format,
          }
  
  
  @register_model_view(ConfigContext, 'add', detail=False)
  @register_model_view(ConfigContext, 'edit')
  