mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-27 02:48:38 -06:00
Move ObjectContactsView back to tenancy.views and using ObjectChildrenView
This commit is contained in:
parent
b822bd7e63
commit
2674e0e6a8
@ -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})(
|
||||||
|
@ -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
|
||||||
|
@ -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 %}
|
||||||
@ -10,56 +11,3 @@
|
|||||||
{% 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 %}
|
|
@ -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
|
||||||
#
|
#
|
||||||
|
Loading…
Reference in New Issue
Block a user