Opened 11 years ago
Closed 11 years ago
#20521 closed New feature (wontfix)
{% local_url %} to extend {% url %} with instrospection of the rendering app
Reported by: | Jorge C. Leitão | Owned by: | nobody |
---|---|---|---|
Component: | Template system | Version: | 1.5 |
Severity: | Normal | Keywords: | tag, url |
Cc: | Jorge C. Leitão | Triage Stage: | Unreviewed |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
==Summary==
New feature: use app's directory tree to resolve urls on templates.
==Motivation==
Currently the {% url %} tag requires the full path of the view or a url name to reverse the correct url of the view. This is limited due to either url name collisions or app's name collision.
To avoid url collisions, django implements a URL namespace, which has to be applied on each app coded to be reusable. One of the biggest problems of the current implementation is the difficultly in using the URL namespace for practical proposes: it is mainly used and (limited to) the case where the same app is being deployed on the same site more than one time.
==Proposal==
I here propose a new templatetag, {% local_url %} and a shortcut to a render, "local_render", that solves the url resolving issue, and does not collide with the current django state.
It works as follows: the local_render passes the argument 'current_app' to the django's render (shortcuts.render) with the full path of the app (package.package.(...)). The {% local_url %} then resolves the url according to the current_app. It is basically a copy of the tag {% url %}, where the "render" of the node is slightly different:
# if the context does not have current_app (case where current_app is not used), render normally
# if the context has current_app (e.g. here 'main.main1.main2'):
try to render with view_name as main.main1.main2.view_name
if NoReverseMatch, try to render with self.view_name=main.main1.main2.view_name
if NoReverseMatch, try to render with self.view_name=main.main1.view_name
if NoReverseMatch, try to render with self.view_name=main.view_name
if NoReverseMatch, try to render with self.view_name=view_name
if NoReverseMatch, raise NoReverseMatch
where view_name is the argument passed in init to self.view_name.
I.e. this basically implements a resolver that works over the app's path.
==Discussion==
- Neither the render nor the tag collide with current implementation (as far as I understood, the current_app is never passed as argument to the url resolver in the {% url %} tag).
- This deprecate the need of URL namespaces for working with templates: the strategy to resolve URL in templates is with this approach according to the directory structure, and apps must have different names inside a directory.
- This agrees with django's spirit of using app's as reusable and modules that complement other app's.
- This allows for views "overload": Consider a child app that is installed on top of a parent which has a view (e.g. views.rules) and a template with {% local_url views.rules %}. The child decides to extend the template (for instance for using the same footers or headers. The child can define a view with the same name (rules) which overloads the parent's view: if the render is called from the child, it uses the view, if it is called from the parent, it is the parent's view. This is the same behavior one would obtain for python classes: the child can always overload a parent's method.
- This idea can be extended to URL resolvers in general, but that requires a major design decision that I don't want to enter for now.
I already have a code which reproduces the behavior I'm suggesting, which I use for a project of mine. I will wait for approach/criticisms to see if it deserves be written in django's standards.
Change History (2)
comment:1 by , 11 years ago
Cc: | added |
---|
comment:2 by , 11 years ago
Resolution: | → wontfix |
---|---|
Status: | new → closed |
I'm going to mark this wontfix, for two reasons:
I'm not claiming you don't (or shouldn't) have a problem in your own code. I'm just questioning whether the problem is so widespread that it warrants the introduction of a second parallel URL reversal scheme.
There might be some merit to your idea of using current_app inside the existing url reversal tools; however, the implementation and consequences of that change would need to be elaborated some more.
If this is an idea you're passionate about, I suggest taking it to django-developers for further discussion. We don't discuss new features on tickets because of the lack of visibility of the discussion. In that discussion, I suggest you spend a lot more time explaining the set of conditions that have led to you getting regular URL name collisions.