Просмотр исходного кода

Split url_name template filter into viewname() and validated_viewname()

Jeremy Stretch 5 лет назад
Родитель
Сommit
128327b8a3

+ 4 - 4
netbox/templates/dcim/device_component.html

@@ -9,7 +9,7 @@
             <ol class="breadcrumb">
                 <li><a href="{% url 'dcim:device_list' %}">Devices</a></li>
                 <li><a href="{{ instance.device.get_absolute_url }}">{{ instance.device }}</a></li>
-                <li><a href="{% url instance|url_name:"list" %}?device_id={{ instance.device.pk }}">{{ instance|meta:"verbose_name_plural"|bettertitle }}</a></li>
+                <li><a href="{% url instance|viewname:"list" %}?device_id={{ instance.device.pk }}">{{ instance|meta:"verbose_name_plural"|bettertitle }}</a></li>
                 <li>{{ instance }}</li>
             </ol>
         </div>
@@ -17,12 +17,12 @@
     <div class="pull-right noprint">
         {% plugin_buttons instance %}
         {% if request.user|can_change:instance %}
-            <a href="{% url instance|url_name:"edit" pk=instance.pk %}" class="btn btn-warning">
+            <a href="{% url instance|viewname:"edit" pk=instance.pk %}" class="btn btn-warning">
                 <span class="fa fa-pencil" aria-hidden="true"></span> Edit
             </a>
         {% endif %}
         {% if request.user|can_delete:instance %}
-            <a href="{% url instance|url_name:"delete" pk=instance.pk %}" class="btn btn-danger">
+            <a href="{% url instance|viewname:"delete" pk=instance.pk %}" class="btn btn-danger">
                 <span class="fa fa-trash" aria-hidden="true"></span> Delete
             </a>
         {% endif %}
@@ -34,7 +34,7 @@
         </li>
         {% if perms.extras.view_objectchange %}
             <li role="presentation"{% if active_tab == 'changelog' %} class="active"{% endif %}>
-                <a href="{% url instance|url_name:"changelog" pk=instance.pk %}">Change Log</a>
+                <a href="{% url instance|viewname:"changelog" pk=instance.pk %}">Change Log</a>
             </li>
         {% endif %}
     </ul>

+ 3 - 3
netbox/templates/utilities/obj_list.html

@@ -9,10 +9,10 @@
         <button type="button" class="btn btn-default" data-toggle="modal" data-target="#tableconfig" title="Configure table"><i class="fa fa-cog"></i> Configure</button>
     {% endif %}
     {% if permissions.add and 'add' in action_buttons %}
-        {% add_button content_type.model_class|url_name:"add" %}
+        {% add_button content_type.model_class|validated_viewname:"add" %}
     {% endif %}
     {% if permissions.add and 'import' in action_buttons %}
-        {% import_button content_type.model_class|url_name:"import" %}
+        {% import_button content_type.model_class|validated_viewname:"import" %}
     {% endif %}
     {% if 'export' in action_buttons %}
         {% export_button content_type %}
@@ -21,7 +21,7 @@
 <h1>{% block title %}{{ content_type.model_class|meta:"verbose_name_plural"|bettertitle }}{% endblock %}</h1>
 <div class="row">
     <div class="col-md-{% if filter_form %}9{% else %}12{% endif %}">
-        {% with bulk_edit_url=content_type.model_class|url_name:"bulk_edit" bulk_delete_url=content_type.model_class|url_name:"bulk_delete" %}
+        {% with bulk_edit_url=content_type.model_class|validated_viewname:"bulk_edit" bulk_delete_url=content_type.model_class|validated_viewname:"bulk_delete" %}
         {% if permissions.change or permissions.delete %}
             <form method="post" class="form form-horizontal">
                 {% csrf_token %}

+ 19 - 3
netbox/utilities/templatetags/helpers.py

@@ -5,6 +5,7 @@ import re
 import yaml
 from django import template
 from django.conf import settings
+from django.urls import NoReverseMatch, reverse
 from django.utils.html import strip_tags
 from django.utils.safestring import mark_safe
 from markdown import markdown
@@ -74,11 +75,26 @@ def meta(obj, attr):
 
 
 @register.filter()
-def url_name(model, action):
+def viewname(model, action):
     """
-    Return the URL name for the given model and action, or None if invalid.
+    Return the view name for the given model and action. Does not perform any validation.
     """
-    return '{}:{}_{}'.format(model._meta.app_label, model._meta.model_name, action)
+    return f'{model._meta.app_label}:{model._meta.model_name}_{action}'
+
+
+@register.filter()
+def validated_viewname(model, action):
+    """
+    Return the view name for the given model and action if valid, or None if invalid.
+    """
+    viewname = f'{model._meta.app_label}:{model._meta.model_name}_{action}'
+    try:
+        # Validate and return the view name. We don't return the actual URL yet because many of the templates
+        # are written to pass a name to {% url %}.
+        reverse(viewname)
+        return viewname
+    except NoReverseMatch:
+        return None
 
 
 @register.filter()