Move ObjectContactsView back to tenancy.views and using ObjectChildrenView

This commit is contained in:
Renato Almeida de Oliveira Zaroubin 2025-04-01 00:04:16 +00:00
parent b822bd7e63
commit 2674e0e6a8
4 changed files with 40 additions and 133 deletions

View File

@ -661,7 +661,7 @@ def register_models(*models):
# Register applicable feature views for the model # Register applicable feature views for the model
if issubclass(model, ContactsMixin): if issubclass(model, ContactsMixin):
register_model_view(model, 'contacts', kwargs={'model': model})( register_model_view(model, 'contacts', kwargs={'model': model})(
'netbox.views.generic.ObjectContactsView' 'tenancy.views.ObjectContactsView'
) )
if issubclass(model, JournalingMixin): if issubclass(model, JournalingMixin):
register_model_view(model, 'journal', kwargs={'model': model})( register_model_view(model, 'journal', kwargs={'model': model})(

View File

@ -12,19 +12,12 @@ from core.tables import JobTable, ObjectChangeTable
from extras.forms import JournalEntryForm from extras.forms import JournalEntryForm
from extras.models import JournalEntry from extras.models import JournalEntry
from extras.tables import JournalEntryTable from extras.tables import JournalEntryTable
from tenancy.models import ContactAssignment
from tenancy.tables import ContactAssignmentTable
from tenancy.filtersets import ContactAssignmentFilterSet
from tenancy.forms import ContactAssignmentFilterForm
from utilities.permissions import get_permission_for_model from utilities.permissions import get_permission_for_model
from utilities.views import ConditionalLoginRequiredMixin, GetReturnURLMixin, ViewTab from utilities.views import ConditionalLoginRequiredMixin, GetReturnURLMixin, ViewTab
from utilities.htmx import htmx_partial
from .base import BaseMultiObjectView from .base import BaseMultiObjectView
from .mixins import ActionsMixin, TableMixin
__all__ = ( __all__ = (
'BulkSyncDataView', 'BulkSyncDataView',
'ObjectContactsView',
'ObjectChangeLogView', 'ObjectChangeLogView',
'ObjectJobsView', 'ObjectJobsView',
'ObjectJournalView', 'ObjectJournalView',
@ -32,75 +25,6 @@ __all__ = (
) )
class ObjectContactsView(ConditionalLoginRequiredMixin, ActionsMixin, TableMixin, View):
"""
Show all Contacts associated with an object. The model class must be passed as a keyword argument when referencing
this view in a URL path. For example:
path('sites/<int:pk>/contacts/', ObjectContactsView.as_view(), name='site_contacts', kwargs={'model': Site}),
Attributes:
base_template: The name of the template to extend. If not provided, "{app}/{model}.html" will be used.
"""
base_template = None
tab = ViewTab(
label=_('Contacts'),
badge=lambda obj: obj.contacts.count(),
permission='tenancy.view_contactassignment',
weight=9000
)
table = ContactAssignmentTable
filterset = ContactAssignmentFilterSet
filterset_form = ContactAssignmentFilterForm
def get(self, request, model, **kwargs):
# Handle QuerySet restriction of parent object if needed
if hasattr(model.objects, 'restrict'):
obj = get_object_or_404(model.objects.restrict(request.user, 'view'), **kwargs)
else:
obj = get_object_or_404(model, **kwargs)
# Gather all Contact Assignments for this object
content_type = ContentType.objects.get_for_model(model)
contactassignments = ContactAssignment.objects.restrict(request.user, 'view').prefetch_related(
'contact',
).filter(
object_type=content_type,
object_id=obj.pk
).order_by('priority', 'contact', 'role')
contactassignments = self.filterset(request.GET, contactassignments, request=request).qs
# Determine the available actions
actions = self.get_permitted_actions(request.user, model=ContactAssignment)
has_bulk_actions = any([a.startswith('bulk_') for a in actions])
table = self.get_table(contactassignments, request, has_bulk_actions)
table.columns.hide('object_type')
table.columns.hide('object')
if htmx_partial(request):
return render(request, 'htmx/table.html', {
'object': obj,
'table': table,
'model': ContactAssignment,
})
# Default to using "<app>/<model>.html" as the template, if it exists. Otherwise,
# fall back to using base.html.
if self.base_template is None:
self.base_template = f"{model._meta.app_label}/{model._meta.model_name}.html"
return render(request, 'tenancy/object_contacts.html', {
'object': obj,
'model': ContactAssignment,
'base_template': self.base_template,
'table': table,
'table_config': f'{table.name}_config',
'filter_form': self.filterset_form(request.GET) if self.filterset_form else None,
'actions': actions,
'tab': self.tab,
'return_url': request.get_full_path(),
})
class ObjectChangeLogView(ConditionalLoginRequiredMixin, View): class ObjectChangeLogView(ConditionalLoginRequiredMixin, View):
""" """
Present a history of changes made to a particular object. The model class must be passed as a keyword argument Present a history of changes made to a particular object. The model class must be passed as a keyword argument

View File

@ -1,4 +1,5 @@
{% extends base_template %}{% load helpers %} {% extends 'generic/object_children.html' %}
{% load helpers %}
{% load i18n %} {% load i18n %}
{% block extra_controls %} {% block extra_controls %}
@ -9,57 +10,4 @@
</a> </a>
{% endwith %} {% endwith %}
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block content %}
{% block table_controls %}
{% include 'inc/table_controls_htmx.html' with table_modal=table_config %}
{% endblock table_controls %}
<form method="post">
{% csrf_token %}
<div class="card">
<div class="htmx-container table-responsive" id="object_list">
{% include 'htmx/table.html' %}
</div>
</div>
<div class="d-print-none mt-2">
{% block bulk_controls %}
<div class="btn-group" role="group">
{# Bulk edit buttons #}
{% block bulk_edit_controls %}
{% with bulk_edit_view=model|validated_viewname:"bulk_edit" %}
{% if 'bulk_edit' in actions and bulk_edit_view %}
<button type="submit" name="_edit"
{% formaction %}="{% url bulk_edit_view %}?return_url={{ return_url }}"
class="btn btn-warning">
<i class="mdi mdi-pencil" aria-hidden="true"></i> {% trans "Edit Selected" %}
</button>
{% endif %}
{% endwith %}
{% endblock bulk_edit_controls %}
</div>
<div class="btn-group" role="group">
{# Bulk delete buttons #}
{% block bulk_delete_controls %}
{% with bulk_delete_view=model|validated_viewname:"bulk_delete" %}
{% if 'bulk_delete' in actions and bulk_delete_view %}
<button type="submit"
{% formaction %}="{% url bulk_delete_view %}?return_url={{ return_url }}"
class="btn btn-danger">
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> {% trans "Delete Selected" %}
</button>
{% endif %}
{% endwith %}
{% endblock bulk_delete_controls %}
</div>
{# Other bulk action buttons #}
{% block bulk_extra_controls %}{% endblock %}
{% endblock bulk_controls %}
</div>
</form>
{% endblock content %}
{% block modals %}
{{ block.super }}
{% table_config_form table %}
{% endblock modals %}

View File

@ -1,13 +1,48 @@
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django.utils.translation import gettext_lazy as _
from netbox.views import generic from netbox.views import generic
from utilities.query import count_related from utilities.query import count_related
from utilities.views import GetRelatedModelsMixin, register_model_view from utilities.views import GetRelatedModelsMixin, ViewTab, register_model_view
from . import filtersets, forms, tables from . import filtersets, forms, tables
from .models import * from .models import *
class ObjectContactsView(generic.ObjectChildrenView):
child_model = ContactAssignment
table = tables.ContactAssignmentTable
filterset = filtersets.ContactAssignmentFilterSet
filterset_form = forms.ContactAssignmentFilterForm
template_name = 'tenancy/object_contacts.html'
tab = ViewTab(
label=_('Contacts'),
badge=lambda obj: obj.contacts.count(),
permission='tenancy.view_contactassignment',
weight=5000
)
def dispatch(self, request, *args, **kwargs):
model = kwargs.pop('model')
self.queryset = model.objects.all()
return super().dispatch(request, *args, **kwargs)
def get_children(self, request, parent):
return ContactAssignment.objects.restrict(request.user, 'view').filter(
object_type=ContentType.objects.get_for_model(parent),
object_id=parent.pk
).order_by('priority', 'contact', 'role')
def get_table(self, *args, **kwargs):
table = super().get_table(*args, **kwargs)
# Hide object columns
table.columns.hide('object_type')
table.columns.hide('object')
return table
# #
# Tenant groups # Tenant groups
# #