瀏覽代碼

Remove the custom querystring template tag (closes #19091)

Removes the deprecated querystring template tag from utilities/templatetags/
helpers.py and updates all 30 call sites across templates to use Django's
built-in querystring tag (available since Django 5.1). The request argument
is dropped since the built-in tag reads from the template context automatically.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Jeremy Stretch 2 周之前
父節點
當前提交
b277d92654

+ 13 - 0
docs/release-notes/version-4.7.md

@@ -0,0 +1,13 @@
+# NetBox v4.7
+
+## v4.7.0 (FUTURE)
+
+### Breaking Changes
+
+### Enhancements
+
+### Other Changes
+
+* [#19091](https://github.com/netbox-community/netbox/issues/19091) - Remove the custom `querystring` template tag (use Django's built-in tag instead)
+
+### REST API Changes

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

@@ -8,7 +8,7 @@
 {% block controls %}
   <div class="col-auto d-print-none">
     <div class="btn-list">
-      <a href="{% url 'dcim:rack_list' %}{% querystring request %}" class="btn btn-primary">
+      <a href="{% url 'dcim:rack_list' %}{% querystring %}" class="btn btn-primary">
         <i class="mdi mdi-format-list-checkbox"></i> {% trans "View List" %}
       </a>
       <select class="btn btn-outline-secondary no-ts rack-view" aria-label="{% trans "Select rack view" %}">
@@ -17,8 +17,8 @@
         <option value="labels-only">{% trans "Labels only" %}</option>
       </select>
       <div class="btn-group" role="group">
-        <a href="{% url 'dcim:rack_elevation_list' %}{% querystring request face='front' %}" class="btn btn-outline-secondary{% if rack_face == 'front' %} active{% endif %}">{% trans "Front" %}</a>
-        <a href="{% url 'dcim:rack_elevation_list' %}{% querystring request face='rear' %}" class="btn btn-outline-secondary{% if rack_face == 'rear' %} active{% endif %}">{% trans "Rear" %}</a>
+        <a href="{% url 'dcim:rack_elevation_list' %}{% querystring face='front' %}" class="btn btn-outline-secondary{% if rack_face == 'front' %} active{% endif %}">{% trans "Front" %}</a>
+        <a href="{% url 'dcim:rack_elevation_list' %}{% querystring face='rear' %}" class="btn btn-outline-secondary{% if rack_face == 'rear' %} active{% endif %}">{% trans "Rear" %}</a>
       </div>
       <div class="dropdown">
         <button type="button" class="btn btn-outline-secondary dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@@ -26,7 +26,7 @@
         </button>
         <ul class="dropdown-menu dropdown-menu-end">
           {% for sort_key, sort_display_name in sort_choices.items %}
-            <li><a class="dropdown-item{% if sort == sort_key %} active{% endif %}" href="{% url 'dcim:rack_elevation_list' %}{% querystring request sort=sort_key %}">{{ sort_display_name }}</a></li>
+            <li><a class="dropdown-item{% if sort == sort_key %} active{% endif %}" href="{% url 'dcim:rack_elevation_list' %}{% querystring sort=sort_key %}">{{ sort_display_name }}</a></li>
           {% endfor %}
         </ul>
       </div>

+ 1 - 1
netbox/templates/dcim/rack_list.html

@@ -4,7 +4,7 @@
 {% load i18n %}
 
 {% block extra_controls %}
-  <a href="{% url 'dcim:rack_elevation_list' %}{% querystring request %}" class="btn btn-primary">
+  <a href="{% url 'dcim:rack_elevation_list' %}{% querystring %}" class="btn btn-primary">
     <i class="mdi mdi-view-day-outline"></i> {% trans "View Elevations" %}
   </a>
 {% endblock %}

+ 1 - 1
netbox/templates/generic/bulk_add.html

@@ -8,7 +8,7 @@
 {% block tabs %}
   <ul class="nav nav-tabs">
     <li class="nav-item">
-      <a href="{{ add_url }}{% querystring request %}" class="nav-link">
+      <a href="{{ add_url }}{% querystring %}" class="nav-link">
         {% trans "Create" %}
       </a>
     </li>

+ 8 - 8
netbox/templates/inc/paginator.html

@@ -19,11 +19,11 @@
           {% if page.has_previous %}
             <li class="page-item">
               {% if htmx %}
-                <a href="#" hx-get="{{ table.htmx_url }}{% querystring request page=page.previous_page_number %}" class="page-link">
+                <a href="#" hx-get="{{ table.htmx_url }}{% querystring page=page.previous_page_number %}" class="page-link">
                   <i class="mdi mdi-chevron-left"></i>
                 </a>
               {% else %}
-                <a href="{% querystring request page=page.previous_page_number %}" class="page-link">
+                <a href="{% querystring page=page.previous_page_number %}" class="page-link">
                   <i class="mdi mdi-chevron-left"></i>
                 </a>
               {% endif %}
@@ -35,11 +35,11 @@
           {% for p in page.smart_pages %}
             <li class="page-item{% if page.number == p %} active" aria-current="page{% endif %}">
               {% if p and htmx %}
-                <a href="#" hx-get="{{ table.htmx_url }}{% querystring request page=p %}" class="page-link">
+                <a href="#" hx-get="{{ table.htmx_url }}{% querystring page=p %}" class="page-link">
                   {{ p }}
                 </a>
               {% elif p %}
-                <a href="{% querystring request page=p %}" class="page-link {% if page.number == p %} active{% endif %}">
+                <a href="{% querystring page=p %}" class="page-link {% if page.number == p %} active{% endif %}">
                   {{ p }}
                 </a>
               {% else %}
@@ -53,11 +53,11 @@
           {% if page.has_next %}
             <li class="page-item">
               {% if htmx %}
-                <a href="#" hx-get="{{ table.htmx_url }}{% querystring request page=page.next_page_number %}" class="page-link">
+                <a href="#" hx-get="{{ table.htmx_url }}{% querystring page=page.next_page_number %}" class="page-link">
                   <i class="mdi mdi-chevron-right"></i>
                 </a>
               {% else %}
-                <a href="{% querystring request page=page.next_page_number %}" class="page-link">
+                <a href="{% querystring page=page.next_page_number %}" class="page-link">
                   <i class="mdi mdi-chevron-right"></i>
                 </a>
               {% endif %}
@@ -89,9 +89,9 @@
             {% for n in page.paginator.get_page_lengths %}
               <li>
                 {% if htmx %}
-                  <a href="#" hx-get="{{ table.htmx_url }}{% querystring request per_page=n %}" class="dropdown-item">{{ n }}</a>
+                  <a href="#" hx-get="{{ table.htmx_url }}{% querystring per_page=n %}" class="dropdown-item">{{ n }}</a>
                 {% else %}
-                  <a href="{% querystring request per_page=n %}" class="dropdown-item">{{ n }}</a>
+                  <a href="{% querystring per_page=n %}" class="dropdown-item">{{ n }}</a>
                 {% endif %}
               </li>
             {% endfor %}

+ 3 - 3
netbox/templates/ipam/inc/ipaddress_edit_header.html

@@ -3,19 +3,19 @@
 
 <ul class="nav nav-tabs">
   <li class="nav-item">
-    <a href="{% url 'ipam:ipaddress_add' %}{% querystring request %}" class="nav-link {% if active_tab == 'add' %}active{% endif %}">
+    <a href="{% url 'ipam:ipaddress_add' %}{% querystring %}" class="nav-link {% if active_tab == 'add' %}active{% endif %}">
       {% if object.pk %}{% trans "Edit" %}{% else %}{% trans "Create" %}{% endif %}
     </a>
   </li>
   {% if 'interface' in request.GET or 'vminterface' in request.GET %}
     <li class="nav-item">
-      <a href="{% url 'ipam:ipaddress_assign' %}{% querystring request %}" class="nav-link {% if active_tab == 'assign' %}active{% endif %}">
+      <a href="{% url 'ipam:ipaddress_assign' %}{% querystring %}" class="nav-link {% if active_tab == 'assign' %}active{% endif %}">
         {% trans "Assign IP" %}
       </a>
     </li>
   {% elif not object.pk %}
     <li class="nav-item">
-      <a href="{% url 'ipam:ipaddress_bulk_add' %}{% querystring request %}" class="nav-link {% if active_tab == 'bulk_add' %}active{% endif %}">
+      <a href="{% url 'ipam:ipaddress_bulk_add' %}{% querystring %}" class="nav-link {% if active_tab == 'bulk_add' %}active{% endif %}">
         {% trans "Bulk Create" %}
       </a>
     </li>

+ 2 - 2
netbox/templates/ipam/inc/max_depth.html

@@ -8,11 +8,11 @@
     <ul class="dropdown-menu" aria-labelledby="max_depth">
         {% if request.GET.depth__lte %}
             <li>
-                <a class="dropdown-item" href="{{ request.path }}{% querystring request depth__lte=None page=1 %}">{% trans "Clear" %}</a>
+                <a class="dropdown-item" href="{{ request.path }}{% querystring depth__lte=None page=1 %}">{% trans "Clear" %}</a>
             </li>
         {% endif %}
         {% for i in 16|as_range %}
-            <li><a class="dropdown-item" href="{{ request.path }}{% querystring request depth__lte=i page=1 %}">
+            <li><a class="dropdown-item" href="{{ request.path }}{% querystring depth__lte=i page=1 %}">
                 {{ i }} {% if request.GET.depth__lte == i %}<i class="mdi mdi-check-bold"></i>{% endif %}
             </a></li>
         {% endfor %}

+ 2 - 2
netbox/templates/ipam/inc/max_length.html

@@ -8,11 +8,11 @@
     <ul class="dropdown-menu" aria-labelledby="max_length">
         {% if request.GET.mask_length__lte %}
             <li>
-                <a class="dropdown-item" href="{{ request.path }}{% querystring request mask_length__lte=None page=1 %}">{% trans "Clear" %}</a>
+                <a class="dropdown-item" href="{{ request.path }}{% querystring mask_length__lte=None page=1 %}">{% trans "Clear" %}</a>
             </li>
         {% endif %}
         {% for i in "4,8,12,16,20,24,28,32,40,48,56,64"|split %}
-            <li><a class="dropdown-item" href="{{ request.path }}{% querystring request mask_length__lte=i page=1 %}">
+            <li><a class="dropdown-item" href="{{ request.path }}{% querystring mask_length__lte=i page=1 %}">
                 {{ i }} {% if request.GET.mask_length__lte == i %}<i class="mdi mdi-check-bold"></i>{% endif %}
             </a></li>
         {% endfor %}

+ 2 - 2
netbox/templates/ipam/inc/prefix_edit_header.html

@@ -3,13 +3,13 @@
 
 <ul class="nav nav-tabs">
   <li class="nav-item">
-    <a href="{% if object.pk %}{% url 'ipam:prefix_edit' pk=object.pk %}{% else %}{% url 'ipam:prefix_add' %}{% querystring request %}{% endif %}" class="nav-link {% if active_tab == 'add' %}active{% endif %}">
+    <a href="{% if object.pk %}{% url 'ipam:prefix_edit' pk=object.pk %}{% else %}{% url 'ipam:prefix_add' %}{% querystring %}{% endif %}" class="nav-link {% if active_tab == 'add' %}active{% endif %}">
       {% if object.pk %}{% trans "Prefix" %}{% else %}{% trans "Create" %}{% endif %}
     </a>
   </li>
   {% if not object.pk %}
     <li class="nav-item">
-      <a href="{% url 'ipam:prefix_bulk_add' %}{% querystring request %}" class="nav-link {% if active_tab == 'bulk_add' %}active{% endif %}">
+      <a href="{% url 'ipam:prefix_bulk_add' %}{% querystring %}" class="nav-link {% if active_tab == 'bulk_add' %}active{% endif %}">
         {% trans "Bulk Create" %}
       </a>
     </li>

+ 3 - 3
netbox/templates/ipam/inc/toggle_available.html

@@ -3,13 +3,13 @@
 
 {% if show_assigned or show_available is not None %}
   <div class="btn-group" role="group">
-    <a href="{{ request.path }}{% querystring request show_assigned='true' show_available='false' %}" class="btn {% if show_assigned and not show_available %}btn-secondary active{% else %}btn-outline-secondary{% endif %}">
+    <a href="{{ request.path }}{% querystring show_assigned='true' show_available='false' %}" class="btn {% if show_assigned and not show_available %}btn-secondary active{% else %}btn-outline-secondary{% endif %}">
       {% trans "Show Assigned" %}
     </a>
-    <a href="{{ request.path }}{% querystring request show_assigned='false' show_available='true' %}" class="btn {% if show_available and not show_assigned %}btn-secondary active{% else %}btn-outline-secondary{% endif %}">
+    <a href="{{ request.path }}{% querystring show_assigned='false' show_available='true' %}" class="btn {% if show_available and not show_assigned %}btn-secondary active{% else %}btn-outline-secondary{% endif %}">
       {% trans "Show Available" %}
     </a>
-    <a href="{{ request.path }}{% querystring request show_assigned='true' show_available='true' %}" class="btn {% if show_available and show_assigned %}btn-secondary active{% else %}btn-outline-secondary{% endif %}">
+    <a href="{{ request.path }}{% querystring show_assigned='true' show_available='true' %}" class="btn {% if show_available and show_assigned %}btn-secondary active{% else %}btn-outline-secondary{% endif %}">
       {% trans "Show All" %}
     </a>
   </div>

+ 1 - 1
netbox/templates/ipam/ipaddress_assign.html

@@ -12,7 +12,7 @@
 {% endblock %}
 
 {% block form %}
-  <form action="{% querystring request %}" method="post" class="form form-horizontal">
+  <form action="{% querystring %}" method="post" class="form form-horizontal">
     {% csrf_token %}
     {% for field in form.hidden_fields %}
       {{ field }}

+ 0 - 24
netbox/utilities/templatetags/helpers.py

@@ -1,5 +1,4 @@
 import json
-import warnings
 from typing import Any
 from urllib.parse import quote
 
@@ -28,7 +27,6 @@ __all__ = (
     'kg_to_pounds',
     'meters_to_feet',
     'percentage',
-    'querystring',
     'startswith',
     'status_from_tag',
     'table_config_form',
@@ -395,28 +393,6 @@ def icon_from_status(status: str = "info") -> str:
 # Tags
 #
 
-@register.simple_tag()
-def querystring(request, **kwargs):
-    """
-    Append or update the page number in a querystring.
-    """
-    warnings.warn(
-        'The querystring template tag is deprecated and will be removed in a future release. Use '
-        'the built-in Django querystring tag instead.',
-        category=FutureWarning,
-    )
-    querydict = request.GET.copy()
-    for k, v in kwargs.items():
-        if v is not None:
-            querydict[k] = str(v)
-        elif k in querydict:
-            querydict.pop(k)
-    querystring = querydict.urlencode(safe='/')
-    if querystring:
-        return '?' + querystring
-    return ''
-
-
 @register.inclusion_tag('helpers/utilization_graph.html')
 def utilization_graph(utilization, warning_threshold=75, danger_threshold=90):
     """