From 10aa34afab6f53ba470c0a26d3609916b154e314 Mon Sep 17 00:00:00 2001 From: "T. Franzel" Date: Sat, 30 Nov 2024 15:21:12 +0700 Subject: [PATCH] Pr1312 (#1339) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Force evaluation of reverse_lazy urls in set_query_parameters. Fixes #1311 Passing reverse_lazy url to SpectacularRedocView errors because set_query_parameters calls urlls.parse.urlparse on url which may not be a string but a 'django.utils.functional.lazy..__proxy__'. Forcing url to be string fixes this issue. * Update plumbing.py * fix second lazy url issue & add test #1312 --------- Co-authored-by: Işık Kaplan --- drf_spectacular/plumbing.py | 2 ++ tests/test_plumbing.py | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/drf_spectacular/plumbing.py b/drf_spectacular/plumbing.py index 879c4eb4..eb4799fb 100644 --- a/drf_spectacular/plumbing.py +++ b/drf_spectacular/plumbing.py @@ -1283,6 +1283,7 @@ def build_mock_request(method, path, view, original_request, **kwargs): def set_query_parameters(url, **kwargs) -> str: """ deconstruct url, safely attach query parameters in kwargs, and serialize again """ + url = str(url) # Force evaluation of reverse_lazy urls scheme, netloc, path, params, query, fragment = urllib.parse.urlparse(url) query = urllib.parse.parse_qs(query) query.update({k: v for k, v in kwargs.items() if v is not None}) @@ -1291,6 +1292,7 @@ def set_query_parameters(url, **kwargs) -> str: def get_relative_url(url: str) -> str: + url = str(url) # Force evaluation of reverse_lazy urls scheme, netloc, path, params, query, fragment = urllib.parse.urlparse(url) return urllib.parse.urlunparse(('', '', path, params, query, fragment)) diff --git a/tests/test_plumbing.py b/tests/test_plumbing.py index cbdafcfe..b1bdc63e 100644 --- a/tests/test_plumbing.py +++ b/tests/test_plumbing.py @@ -16,13 +16,14 @@ from django.conf.urls import include from django.db import models from django.urls import re_path +from django.utils.functional import lazystr from rest_framework import generics, serializers from drf_spectacular.openapi import AutoSchema from drf_spectacular.plumbing import ( analyze_named_regex_pattern, build_basic_type, build_choice_field, detype_pattern, - follow_field_source, force_instance, get_list_serializer, is_field, is_serializer, - resolve_type_hint, safe_ref, + follow_field_source, force_instance, get_list_serializer, get_relative_url, is_field, + is_serializer, resolve_type_hint, safe_ref, set_query_parameters, ) from drf_spectacular.validation import validate_schema from tests import generate_schema @@ -437,3 +438,13 @@ def test_safe_ref(): schema = safe_ref(schema) assert schema == {'$ref': '#/components/schemas/Foo'} assert safe_ref(schema) == safe_ref(schema) + + +def test_url_tooling_with_lazy_url(): + some_url = "http://api.example.org/accounts/" + + assert get_relative_url(some_url) == "/accounts/" + assert set_query_parameters(some_url, foo=123) == some_url + "?foo=123" + + assert get_relative_url(lazystr(some_url)) == "/accounts/" + assert set_query_parameters(lazystr(some_url), foo=123) == some_url + "?foo=123"