python: Use Django 5.2 reverse(…, query=…).

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg
2025-06-11 16:56:58 -07:00
committed by Tim Abbott
parent b10bf1dd20
commit 717cf60edf
10 changed files with 28 additions and 70 deletions

View File

@@ -4,7 +4,6 @@ from dataclasses import dataclass
from datetime import datetime
from decimal import Decimal
from typing import Any
from urllib.parse import urlencode
from django.conf import settings
from django.db import connection
@@ -19,7 +18,6 @@ from psycopg2.sql import Composable
from corporate.models.licenses import LicenseLedger
from corporate.models.plans import CustomerPlan
from zerver.lib.pysa import mark_sanitized
from zerver.lib.url_encoding import append_url_query_string
from zerver.models import Realm
from zilencer.models import (
RemoteCustomerUserCount,
@@ -139,16 +137,12 @@ def realm_stats_link(realm_str: str) -> Markup:
def user_support_link(email: str) -> Markup:
support_url = reverse("support")
query = urlencode({"q": email})
url = append_url_query_string(support_url, query)
url = reverse("support", query={"q": email})
return Markup('<a href="{url}"><i class="fa fa-gear"></i></a>').format(url=url)
def realm_support_link(realm_str: str) -> Markup:
support_url = reverse("support")
query = urlencode({"q": realm_str})
url = append_url_query_string(support_url, query)
url = reverse("support", query={"q": realm_str})
return Markup('<a href="{url}">{realm}</i></a>').format(url=url, realm=realm_str)
@@ -166,9 +160,7 @@ def remote_installation_stats_link(server_id: int) -> Markup:
def remote_installation_support_link(hostname: str) -> Markup:
support_url = reverse("remote_servers_support")
query = urlencode({"q": hostname})
url = append_url_query_string(support_url, query)
url = reverse("remote_servers_support", query={"q": hostname})
return Markup('<a href="{url}"><i class="fa fa-gear"></i></a>').format(url=url)

View File

@@ -203,11 +203,11 @@ def authenticated_remote_server_management_endpoint(
# That means that we can do it universally whether the user has an expired
# identity_dict, or just lacks any form of authentication info at all - there
# are no security concerns since this is just a local redirect.
url = reverse("remote_billing_legacy_server_login")
page_type = get_next_page_param_from_request_path(request)
if page_type is not None:
query = urlencode({"next_page": page_type})
url = append_url_query_string(url, query)
url = reverse(
"remote_billing_legacy_server_login",
query=None if page_type is None else {"next_page": page_type},
)
# Return error for AJAX requests with url.
if (

View File

@@ -52,7 +52,6 @@ from zerver.lib.send_email import (
send_email_to_users_with_billing_access_and_realm_owners,
)
from zerver.lib.timestamp import datetime_to_timestamp, timestamp_to_datetime
from zerver.lib.url_encoding import append_url_query_string
from zerver.lib.utils import assert_is_not_none
from zerver.models import Realm, RealmAuditLog, Stream, UserProfile
from zerver.models.realm_audit_logs import AuditLogEventType
@@ -378,10 +377,7 @@ def payment_method_string(stripe_customer: stripe.Customer) -> str:
def build_support_url(support_view: str, query_text: str) -> str:
support_realm_url = get_realm(settings.STAFF_SUBDOMAIN).url
support_url = urljoin(support_realm_url, reverse(support_view))
query = urlencode({"q": query_text})
support_url = append_url_query_string(support_url, query)
return support_url
return urljoin(support_realm_url, reverse(support_view, query={"q": query_text}))
def get_configured_fixed_price_plan_offer(

View File

@@ -1,6 +1,5 @@
from dataclasses import asdict, dataclass
from typing import TYPE_CHECKING
from urllib.parse import urlencode
import orjson
from django.conf import settings
@@ -104,7 +103,7 @@ def plans_view(request: HttpRequest) -> HttpResponse:
)
if is_subdomain_root_or_alias(request):
# If we're on the root domain, we make this link first ask you which organization.
context.sponsorship_url = f"/accounts/go/?{urlencode({'next': context.sponsorship_url})}"
context.sponsorship_url = reverse("realm_redirect", query={"next": context.sponsorship_url})
if realm is not None:
if realm.plan_type == Realm.PLAN_TYPE_SELF_HOSTED and settings.PRODUCTION:

View File

@@ -611,7 +611,7 @@ def remote_billing_legacy_server_confirm_login(
raise RemoteBillingAuthenticationError
except (RemoteBillingIdentityExpiredError, RemoteBillingAuthenticationError):
return HttpResponseRedirect(
reverse("remote_billing_legacy_server_login") + f"?next_page={next_page}"
reverse("remote_billing_legacy_server_login", query={"next_page": next_page})
)
rate_limit_error_response = check_rate_limits(request, remote_server)

View File

@@ -5,7 +5,7 @@ from dataclasses import dataclass
from datetime import timedelta
from operator import attrgetter
from typing import Annotated, Any, Literal
from urllib.parse import urlencode, urlsplit
from urllib.parse import urlsplit
from django import forms
from django.conf import settings
@@ -550,9 +550,7 @@ def support(
request.session["success_message"] = (
f"Subdomain changed from {old_subdomain} to {new_subdomain}"
)
return HttpResponseRedirect(
reverse("support") + "?" + urlencode({"q": new_subdomain})
)
return HttpResponseRedirect(reverse("support", query={"q": new_subdomain}))
elif status is not None:
if status == "active":
do_send_realm_reactivation_email(realm, acting_user=acting_user)

View File

@@ -3,7 +3,7 @@ from collections.abc import Sequence
from datetime import datetime, timedelta
from typing import TYPE_CHECKING
from unittest.mock import patch
from urllib.parse import quote, urlencode
from urllib.parse import quote
import orjson
import time_machine
@@ -2074,7 +2074,7 @@ so we didn't send them an invitation. We did send invitations to everyone else!"
self.assertEqual(response.status_code, 302)
self.assertEqual(
response["Location"],
reverse("login") + "?" + urlencode({"email": email, "already_registered": 1}),
reverse("login", query={"email": email, "already_registered": 1}),
)
def test_confirmation_key_cant_be_reused(self) -> None:

View File

@@ -624,7 +624,6 @@ def oauth_redirect_to_root(
url: str,
sso_type: str,
is_signup: bool,
extra_url_params: Mapping[str, str],
# Protect the above parameters from being processed as kwargs
# provided by @typed_endpoint by marking them as mandatory
# positional parameters.
@@ -662,8 +661,6 @@ def oauth_redirect_to_root(
if next:
params["next"] = next
params = {**params, **extra_url_params}
return redirect(append_url_query_string(main_site_url, urlencode(params)))
@@ -691,8 +688,7 @@ def start_remote_user_sso(request: HttpRequest) -> HttpResponse:
/accounts/login/sso may have Apache intercepting requests to it
to do authentication, so we need this additional endpoint.
"""
query = request.META["QUERY_STRING"]
return redirect(append_url_query_string(reverse(remote_user_sso), query))
return redirect(reverse(remote_user_sso, query=request.GET))
@handle_desktop_flow
@@ -701,7 +697,6 @@ def start_social_login(
backend: str,
extra_arg: str | None = None,
) -> HttpResponse:
backend_url = reverse("social:begin", args=[backend])
extra_url_params: dict[str, str] = {}
if backend == "saml":
if not SAMLAuthBackend.check_config():
@@ -730,10 +725,9 @@ def start_social_login(
return oauth_redirect_to_root(
request,
backend_url,
reverse("social:begin", args=[backend], query=extra_url_params),
"social",
False,
extra_url_params,
)
@@ -743,7 +737,6 @@ def start_social_signup(
backend: str,
extra_arg: str | None = None,
) -> HttpResponse:
backend_url = reverse("social:begin", args=[backend])
extra_url_params: dict[str, str] = {}
if backend == "saml":
if not SAMLAuthBackend.check_config():
@@ -757,10 +750,9 @@ def start_social_signup(
extra_url_params = {"idp": extra_arg}
return oauth_redirect_to_root(
request,
backend_url,
reverse("social:begin", args=[backend], query=extra_url_params),
"social",
True,
extra_url_params,
)
@@ -922,10 +914,7 @@ def login_page(
redirect_to = get_safe_redirect_to(next, request.user.realm.url)
return HttpResponseRedirect(redirect_to)
if is_subdomain_root_or_alias(request) and settings.ROOT_DOMAIN_LANDING_PAGE:
redirect_url = reverse("realm_redirect")
if request.GET:
redirect_url = append_url_query_string(redirect_url, request.GET.urlencode())
return HttpResponseRedirect(redirect_url)
return HttpResponseRedirect(reverse("realm_redirect", query=request.GET))
realm = get_realm_from_request(request)
if realm and realm.deactivated:
@@ -1256,9 +1245,7 @@ def logout_view(request: HttpRequest) -> HttpResponse:
def password_reset(request: HttpRequest) -> HttpResponse:
if is_subdomain_root_or_alias(request) and settings.ROOT_DOMAIN_LANDING_PAGE:
redirect_url = append_url_query_string(
reverse("realm_redirect"), urlencode({"next": reverse("password_reset")})
)
redirect_url = reverse("realm_redirect", query={"next": reverse("password_reset")})
return HttpResponseRedirect(redirect_url)
try:

View File

@@ -771,10 +771,7 @@ def registration_helper(
# user-friendly error message, but it doesn't
# particularly matter, because the registration form
# is hidden for most users.
view_url = reverse("login")
query = urlencode({"email": email})
redirect_url = append_url_query_string(view_url, query)
return HttpResponseRedirect(redirect_url)
return HttpResponseRedirect(reverse("login", query={"email": email}))
else:
assert isinstance(user, UserProfile)
user_profile = user
@@ -1032,11 +1029,7 @@ def send_confirm_registration_email(
def redirect_to_email_login_url(email: str) -> HttpResponseRedirect:
login_url = reverse("login")
redirect_url = append_url_query_string(
login_url, urlencode({"email": email, "already_registered": 1})
)
return HttpResponseRedirect(redirect_url)
return HttpResponseRedirect(reverse("login", query={"email": email, "already_registered": 1}))
@typed_endpoint
@@ -1305,17 +1298,16 @@ def create_realm(request: HttpRequest, creation_key: str | None = None) -> HttpR
if key_record is not None:
key_record.delete()
new_realm_send_confirm_url = reverse("new_realm_send_confirm")
query = urlencode(
{
url = reverse(
"new_realm_send_confirm",
query={
"email": email,
"realm_name": realm_name,
"realm_type": realm_type,
"realm_default_language": realm_default_language,
"realm_subdomain": realm_subdomain,
}
},
)
url = append_url_query_string(new_realm_send_confirm_url, query)
return HttpResponseRedirect(url)
else:
default_language_code = get_browser_language_code(request)
@@ -1468,10 +1460,7 @@ def accounts_home(
if settings.CORPORATE_ENABLED:
return render(request, "500.html", status=500)
return config_error(request, "smtp")
signup_send_confirm_url = reverse("signup_send_confirm")
query = urlencode({"email": email})
url = append_url_query_string(signup_send_confirm_url, query)
return HttpResponseRedirect(url)
return HttpResponseRedirect(reverse("signup_send_confirm", query={"email": email}))
else:
form = HomepageForm(realm=realm)

View File

@@ -19,7 +19,6 @@ from abc import ABC, abstractmethod
from collections.abc import Callable
from email.headerregistry import Address
from typing import Any, TypedDict, TypeVar, cast
from urllib.parse import urlencode
import magic
import orjson
@@ -88,7 +87,6 @@ from zerver.lib.request import RequestNotes
from zerver.lib.sessions import delete_user_sessions
from zerver.lib.subdomains import get_subdomain
from zerver.lib.types import ProfileDataElementUpdateDict
from zerver.lib.url_encoding import append_url_query_string
from zerver.lib.users import check_full_name, validate_user_custom_profile_field
from zerver.models import (
CustomProfileField,
@@ -1637,9 +1635,8 @@ def redirect_to_login(realm: Realm) -> HttpResponseRedirect:
def redirect_deactivated_user_to_login(realm: Realm, email: str) -> HttpResponseRedirect:
# Specifying the template name makes sure that the user is not redirected to dev_login in case of
# a deactivated account on a test server.
login_url = reverse("login_page", kwargs={"template_name": "zerver/login.html"})
redirect_url = append_url_query_string(
realm.url + login_url, urlencode({"is_deactivated": email})
redirect_url = realm.url + reverse(
"login_page", kwargs={"template_name": "zerver/login.html"}, query={"is_deactivated": email}
)
return HttpResponseRedirect(redirect_url)