#20048 add get_action_url utility function

This commit is contained in:
Arthur 2025-08-07 13:48:19 -07:00
parent fa262adc6f
commit d7e92bdfb7
4 changed files with 16 additions and 25 deletions

View File

@ -25,7 +25,7 @@ from utilities.permissions import get_permission_for_model
from utilities.querydict import normalize_querydict, prepare_cloned_fields
from utilities.request import safe_for_redirect
from utilities.tables import get_table_configs
from utilities.views import GetReturnURLMixin, get_viewname
from utilities.views import GetReturnURLMixin, get_action_url
from .base import BaseObjectView
from .mixins import ActionsMixin, TableMixin
from .utils import get_prerequisite_model
@ -436,8 +436,7 @@ class ObjectDeleteView(GetReturnURLMixin, BaseObjectView):
# If this is an HTMX request, return only the rendered deletion form as modal content
if htmx_partial(request):
viewname = get_viewname(self.queryset.model, action='delete')
form_url = reverse(viewname, kwargs={'pk': obj.pk})
form_url = get_action_url(self.queryset.model, action='delete', kwargs={'pk': obj.pk})
return render(request, 'htmx/delete_form.html', {
'object': obj,
'object_type': self.queryset.model._meta.verbose_name,

View File

@ -2,10 +2,9 @@ import django_filters
from django import forms
from django.conf import settings
from django.forms import BoundField
from django.urls import reverse
from utilities.forms import widgets
from utilities.views import get_viewname
from utilities.views import get_action_url
__all__ = (
'DynamicChoiceField',
@ -173,13 +172,12 @@ class DynamicModelChoiceMixin:
# Set the data URL on the APISelect widget (if not already set)
if not widget.attrs.get('data-url'):
viewname = get_viewname(self.queryset.model, action='list', rest_api=True)
widget.attrs['data-url'] = reverse(viewname)
widget.attrs['data-url'] = get_action_url(self.queryset.model, action='list', rest_api=True)
# Include quick add?
if self.quick_add:
widget.quick_add_context = {
'url': reverse(get_viewname(self.model, 'add')),
'url': get_action_url(self.model, action='add'),
'params': {},
}
for k, v in self.quick_add_params.items():

View File

@ -8,7 +8,7 @@ from core.models import ObjectType
from extras.models import Bookmark, ExportTemplate, Subscription
from netbox.models.features import NotificationsMixin
from utilities.querydict import prepare_cloned_fields
from utilities.views import get_viewname
from utilities.views import get_action_url
__all__ = (
'action_buttons',
@ -110,9 +110,8 @@ def subscribe_button(context, instance):
@register.inclusion_tag('buttons/clone.html')
def clone_button(instance):
# Resolve URL path
viewname = get_viewname(instance, 'add')
try:
url = reverse(viewname)
url = get_action_url(instance, action='add')
except NoReverseMatch:
return {
'url': None,
@ -128,8 +127,7 @@ def clone_button(instance):
# TODO: Remove in NetBox v4.6
@register.inclusion_tag('buttons/edit.html')
def edit_button(instance):
viewname = get_viewname(instance, 'edit')
url = reverse(viewname, kwargs={'pk': instance.pk})
url = get_action_url(instance, action='edit', kwargs={'pk': instance.pk})
return {
'url': url,
@ -140,8 +138,7 @@ def edit_button(instance):
# TODO: Remove in NetBox v4.6
@register.inclusion_tag('buttons/delete.html')
def delete_button(instance):
viewname = get_viewname(instance, 'delete')
url = reverse(viewname, kwargs={'pk': instance.pk})
url = get_action_url(instance, action='delete', kwargs={'pk': instance.pk})
return {
'url': url,
@ -152,8 +149,7 @@ def delete_button(instance):
# TODO: Remove in NetBox v4.6
@register.inclusion_tag('buttons/sync.html')
def sync_button(instance):
viewname = get_viewname(instance, 'sync')
url = reverse(viewname, kwargs={'pk': instance.pk})
url = get_action_url(instance, action='sync', kwargs={'pk': instance.pk})
return {
'label': _('Sync'),
@ -169,7 +165,7 @@ def sync_button(instance):
@register.inclusion_tag('buttons/add.html')
def add_button(model, action='add'):
try:
url = reverse(get_viewname(model, action))
url = get_action_url(model, action=action)
except NoReverseMatch:
url = None
@ -183,7 +179,7 @@ def add_button(model, action='add'):
@register.inclusion_tag('buttons/import.html')
def import_button(model, action='bulk_import'):
try:
url = reverse(get_viewname(model, action))
url = get_action_url(model, action=action)
except NoReverseMatch:
url = None
@ -219,7 +215,7 @@ def export_button(context, model):
@register.inclusion_tag('buttons/bulk_edit.html', takes_context=True)
def bulk_edit_button(context, model, action='bulk_edit', query_params=None):
try:
url = reverse(get_viewname(model, action))
url = get_action_url(model, action=action)
if query_params:
url = f'{url}?{query_params.urlencode()}'
except NoReverseMatch:
@ -236,7 +232,7 @@ def bulk_edit_button(context, model, action='bulk_edit', query_params=None):
@register.inclusion_tag('buttons/bulk_delete.html', takes_context=True)
def bulk_delete_button(context, model, action='bulk_delete', query_params=None):
try:
url = reverse(get_viewname(model, action))
url = get_action_url(model, action=action)
if query_params:
url = f'{url}?{query_params.urlencode()}'
except NoReverseMatch:

View File

@ -1,10 +1,9 @@
from django import template
from django.urls import reverse
from django.urls.exceptions import NoReverseMatch
from django.utils.module_loading import import_string
from netbox.registry import registry
from utilities.views import get_viewname
from utilities.views import get_action_url
__all__ = (
'model_view_tabs',
@ -39,10 +38,9 @@ def model_view_tabs(context, instance):
continue
if attrs := tab.render(instance):
viewname = get_viewname(instance, action=config['name'])
active_tab = context.get('tab')
try:
url = reverse(viewname, args=[instance.pk])
url = get_action_url(instance, action=config['name'], kwargs={'pk': instance.pk})
except NoReverseMatch:
# No URL has been registered for this view; skip
continue