-
-
Notifications
You must be signed in to change notification settings - Fork 930
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Change url_for
signature to return a URL
instance
#1385
Conversation
Mutually exclusive with #1364 |
I think the second approach would make more sense anyway. |
I am curious about one thing: Why not just create URL based on the returned results of url_for? Then let users add query parameters by themselves. It seems more concise. |
Well It is possible. But it could be a useful feature, specially in the Jinja2 templating and less verbose. |
I too much prefer the explicit approach (as proposed by @tomchristie in #560 (comment)). This gives peace of mind that one did not accidentally mix around some path and query parameters. If we want something less verbose we might consider a shorthand for this operation like |
I'm not really sure if I understand correctly. But the comment you've quoted is suggesting that we do not change anything and leave to the end users to add query parameters to the |
Maybe I didn't express myself well enough. I mean by this is that just wrap the previous url_for method to return a URL, and then the user adds or modifies the parameters themselves. Like this: request.url_for("endpoint_name", key=value).include_query_params(name=value).__str__() |
@abersheeran thanks for the clarification. This is exactly the first approach and what Tom Christie mentioned. But that will be a backwards-incompatible change, I think. If it's decided we can do it I'll update the PR. |
Reviewing what Flask and Django do here...
|
Which one do you think would be more appropriate here? How do we decide? |
I guess my preference would be if it already returned a |
Yes, I think that makes sense. |
Given that both would be a breaking change I would strongly prefer the former. Why would both changes be breaking? Well it is a feasible use case to call Also if we adopt the flask style there are certain ambiguities like what should happen in the following case: async def homepage(request):
return JSONResponse({'hello': request.url_for("homepage", foobar="321")})
routes = [
Route("/", endpoint=homepage),
Route("/{foobar}", endpoint=homepage)
]
app = Starlette(debug=True, routes=routes) Should it return However if we choose to return an URL instance there is no such confusing/unexpected behaviour. Apart from that the most common use cases I can think of ( |
I totally agree that returning a And I think Jinja2 would already call |
Could this be handled as a deprecation? It seems like the general consensus is that the API returning |
@adriangb I'm not sure how the deprecation will help. Now we are in 0.17.0 will we deprecate it in 0.18.0 or 1.0.0? I mean if we were on a major release like 1.17.0 it would make sense to deprecate in 2.0.0 but as you said since we don't have a major release, practically this can change. |
Even if it's not required, it can soften the blow. The other pro is you might get someone pop into the discussion with good feedback because they saw the warning. For what it's worth, I would do something like deprecate in 0.18.0 and change in 0.19.0 or some other pre 1.0 release. I think there's precedent for this with startup events / lifespan right? |
Let's wait for @tomchristie input on this. |
c28d9e9
to
fa3fbf1
Compare
What would be the new signature? @aminalaee @adriangb |
Looks like there's two options being discussed:
Bringing in #611 I prefer |
I think there's also the possibility of doing something like Flask does: url_for(name: str, **params: Any) -> str To use any existing params as path parameters and use the remaining as query parameters. |
Yes though that is ambiguous in some cases (#1385 (comment)) and may lead to confusion. Even if deciding for one variant in ambiguous cases there would be no way to archive the opposite way if one requires that. |
Actually, the question I wanted to ask is: "what's the deprecation path mentioned above?" |
I've read the thread again, and it looks like we are more in favor of having a Also, notice that this doesn't break jinja2 templates. I'm fine with returning |
I use this approach quite a long time and the one downside I have is that I have to call But, in templates, it is a breeze of fresh air. <a href="{{ request.url.include_query_params(search='term') }}">home</a> It is a way simpler than making and using a dict in the endpoint callable or template. |
@Kludex I will update the PR then based on the agreement. |
I'm interested in this as well, mostly for template, using the jinja2 url_for most of the time but this PR is missing to update the signature in here: starlette/starlette/templating.py Line 82 in 337ae24
|
@euri10 Thanks, I need to update the PR. |
9cc848f
to
27eab5d
Compare
Request.url_for
query parametersurl_for
signature to return a URL
instance
I think adding a shortcut method And also I didn't see any mention of return type of |
Maybe we can add the |
The way it is right now doesn't solve the issue, right? |
Not sure what you mean, but this will solve the initial issue and query params can be added to the output of url_for. |
It looks like all involved already agreed that this is a better API, our only concern was it being a breaking change. |
Simple implementation for #560 to start a discussion.
url_for
only supports path parameters and in some scenarios like pagination, it would be useful to add query parameters to it.and based on the discussion in the issue we could do one of the following:
We can make
url_for
return aURL
instance that could use the existinginclude_query_params
. I think this won't be a backwards-compatible change, as we're changing the signature ofurl_for
.We could also do something like Flask does, use anything that matches as path parameters, and use the rest as query params. I don't think. this will be a backwards-compatible change either (Not 100% sure but I guess this will have a more limited impact but still there's a chance some clients might depend on
NoMatchFound
instead of getting query params).Update: Based on the discussions it's been decided to change the url_for signature to return a URL instance which will enable the caller to
include_query_params
to the URL both in application and templates.