content: import re
  from collections import namedtuple
  
  from django.conf import settings
  from django.contrib import messages
  from django.contrib.contenttypes.models import ContentType
  from django.core.cache import cache
  from django.shortcuts import redirect, render
  from django.utils.translation import gettext_lazy as _
  from django.views.generic import View
  from django.views.static import serve
  from django_tables2 import RequestConfig
  from packaging import version
  
  from extras.constants import DEFAULT_DASHBOARD
  from extras.dashboard.utils import get_dashboard, get_default_dashboard
  from netbox.forms import SearchForm
  from netbox.search import LookupTypes
  from netbox.search.backends import search_backend
  from netbox.tables import SearchTable
  from utilities.htmx import htmx_partial
  from utilities.paginator import EnhancedPaginator, get_paginate_count
  from utilities.views import ConditionalLoginRequiredMixin, TokenConditionalLoginRequiredMixin
  
  __all__ = (
      'HomeView',
      'MediaView',
      'SearchView',
  )
  
  Link = namedtuple('Link', ('label', 'viewname', 'permission', 'count'))
  
  
  class HomeView(ConditionalLoginRequiredMixin, View):
      template_name = 'home.html'
  
      def get(self, request):
          if settings.LOGIN_REQUIRED and not request.user.is_authenticated:
              return redirect('login')
  
          # Construct the user's custom dashboard layout
          try:
              dashboard = get_dashboard(request.user).get_layout()
          except Exception:
              messages.error(request, _(
                  "There was an error loading the dashboard configuration. A default dashboard is in use."
              ))
              dashboard = get_default_dashboard(config=DEFAULT_DASHBOARD).get_layout()
  
          # Check whether a new release is available. (Only for staff/superusers.)
          new_release = None
          if request.user.is_staff or request.user.is_superuser:
              latest_release = cache.get('latest_release')
              if latest_release:
                  release_version, release_url = latest_release
                  if release_version > version.parse(settings.RELEASE.version):
                      new_release = {
                          'version': str(release_version),
                          'url': release_url,
                      }
  
          return render(request, self.template_name, {
              'dashboard': dashboard,
              'new_release': new_release,
          })
  
  
  class SearchView(ConditionalLoginRequiredMixin, View):
  
      def get(self, request):
          results = []
          highlight = None
  
          # Initialize search form
          form = SearchForm(request.GET) if 'q' in request.GET else SearchForm()
  
          if form.is_valid():
  
              # Restrict results by object type
              object_types = []
              for obj_type in form.cleaned_data['obj_types']:
                  app_label, model_name = obj_type.split('.')
                  object_types.append(ContentType.objects.get_by_natural_key(app_label, model_name))
  
              lookup = form.cleaned_data['lookup'] or LookupTypes.PARTIAL
              results = search_backend.search(
                  form.cleaned_data['q'],
                  user=request.user,
                  object_types=object_types,
                  lookup=lookup
              )
  
              # If performing a regex search, pass the highlight value as a compiled pattern
              if form.cleaned_data['lookup'] == LookupTypes.REGEX:
                  try:
                      highlight = re.compile(f"({form.cleaned_data['q']})", flags=re.IGNORECASE)
                  except re.error:
                      pass
              elif form.cleaned_data['lookup'] != LookupTypes.EXACT:
                  highlight = form.cleaned_data['q']
  
          table = SearchTable(results, highlight=highlight)
  
          # Paginate the table results
          RequestConfig(request, {
              'paginator_class': EnhancedPaginator,
              'per_page': get_paginate_count(request)
          }).configure(table)
  
          # If this is an HTMX request, return only the rendered table HTML
          if htmx_partial(request):
              return render(request, 'htmx/table.html', {
                  'table': table,
              })
  
          return render(request, 'search.html', {
              'form': form,
              'table': table,
          })
  
  
  class MediaView(TokenConditionalLoginRequiredMixin, View):
      """
      Wrap Django's serve() view to enforce LOGIN_REQUIRED for static media.
      """
      def get(self, request, path):
          return serve(request, path, document_root=settings.MEDIA_ROOT)
  