#37268 closed Bug (duplicate)
django 6.1 breaks Media objects with reverse_lazy entries
| Reported by: | alex | Owned by: | |
|---|---|---|---|
| Component: | Forms | Version: | 6.1 |
| Severity: | Normal | Keywords: | |
| Cc: | Johannes Maron | Triage Stage: | Unreviewed |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Problem
sometimes you want to use reverse_lazy for referencing internal urls in forms, widgets and other Media objects.
With the new change to Script, Stylesheet, ... this fails. Both classes cannot lazy load and when a lazy object is defined it is tried to access .__html__() which fails.
What should happen instead is to resolve reverse_lazy when it is really required. Both classes should support lazy objects too.
Why reverse won't work in such situations:
This won't work in admin. Calling reverse too early; e.g. when defining the media object can break the application.
Change History (7)
comment:1 by , 3 weeks ago
| Resolution: | → duplicate |
|---|---|
| Status: | new → closed |
comment:2 by , 3 weeks ago
| Cc: | added |
|---|---|
| Resolution: | duplicate |
| Severity: | Normal → Release blocker |
| Status: | closed → new |
| Triage Stage: | Unreviewed → Accepted |
| Type: | Uncategorized → Bug |
Django 6.0.8:
>>> from django.forms import Media >>> from django.urls import reverse_lazy >>> media = Media(js=reverse_lazy("reports"))
With the PR for #37262, thus not a duplicate:
>>> media = Media(js=reverse_lazy("reports")) Traceback (most recent call last): File "<console>", line 1, in <module> File "/Users/jwalls/django/django/forms/widgets.py", line 151, in __init__ self._js_lists = [self._normalize_js(js)] ~~~~~~~~~~~~~~~~~~^^^^ File "/Users/jwalls/django/django/forms/widgets.py", line 163, in _normalize_js for path in js ^^ File "/Users/jwalls/django/django/utils/functional.py", line 187, in __wrapper__ result = func(*self._args, **self._kw) File "/Users/jwalls/django/django/urls/base.py", line 98, in reverse resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) File "/Users/jwalls/django/django/urls/resolvers.py", line 842, in _reverse_with_prefix raise NoReverseMatch(msg) django.urls.exceptions.NoReverseMatch: Reverse for 'reports' not found. 'reports' is not a valid view function or pattern name.
We document using reverse_lazy for the Stylesheet(MediaAsset) class:
class FeedWithStylesheetView(Feed):
stylesheets = [
reverse_lazy("your-custom-view-name"),
]
So using it in Media(js=...) seems reasonable. Thanks for the report.
This probably makes rendering CSP nonces more difficult, so I'm cc'ing other knowledgable folks who might speak to implementation strategy or what caveats we might need to document.
comment:3 by , 3 weeks ago
| Resolution: | → needsnewfeatureprocess |
|---|---|
| Severity: | Release blocker → Normal |
| Status: | new → closed |
| Triage Stage: | Accepted → Unreviewed |
| Type: | Bug → New feature |
Thanks for alerting me to this issue.
I don't think it's strictly a duplicate, and even with Adams patch, the hasattr check will resolve lazy objects.
If we want to address this we will need to only normalize objects during rendering and will also need to defer the media object merging.
Considering that we never really supported this, and there are not tests for this, I would consider this a feature request, not a bug.
follow-up: 6 comment:4 by , 3 weeks ago
Looks like both were commented on at the same time. I would still consider this a new feature, not a bug. But you are the expert; however, adding support will be very painful.
comment:5 by , 3 weeks ago
| Cc: | removed |
|---|
comment:6 by , 3 weeks ago
| Resolution: | needsnewfeatureprocess → duplicate |
|---|---|
| Type: | New feature → Bug |
Replying to Johannes Maron:
Looks like both were commented on at the same time. I would still consider this a new feature, not a bug. But you are the expert; however, adding support will be very painful.
I think the expert is you, not me :-)
Replying to Jacob Walls:
We document using reverse_lazy for the Stylesheet(MediaAsset) class:
I got mixed up... the Feed.stylesheet is not implemented using Media. Maybe similar use case in spirit at best.
Replying to Johannes Maron:
even with Adams patch, the hasattr check will resolve lazy objects.
Luckily for us, that's not what I see:
>>> from django.urls import reverse_lazy >>> js = reverse_lazy("my.js") >>> hasattr(js, "__html__") False >>> str(js) # failure from URLs not being available Traceback (most recent call last):
So, this may be a dupe of #37262, if it so happens that Script objects can accept reverse_lazy() objects just fine. Alex only said the __html__ call was the problem.
Alex, may I ask you to check the PR linked in comment:1? Thanks!
comment:7 by , 3 weeks ago
| Cc: | added |
|---|
Thanks for the report. This seems to be a duplicate of #37262
Does the patch at https://github.com/django/django/pull/21752 work for you. Your feedback there would be welcomed.