>
> I think it's an unlikely case anyway, but out of curiosity what are the 
> workarounds?


In the case of a 2-tuple, just pass (admin.site.urls[0], 'dashboard'). In 
the case of a module, you'll have to directly import the module and pass a 
(patterns, app_name) tuple. 

If an app has templates and view code that are reversing 
> <app_name>:<view_name>, then changing the app name (e.g. by an undocumented 
> feature, passing a (patterns, app_name) tuple), then all those URLs will 
> break. Unless I'm missing something, an app *must always* be installed with 
> the app name that is hard coded in its templates and view code, so there is 
> no workaround for app namespace conflicts?
>
 

Does or would it work to allow two apps with the same app namespace, as 
> long as they both are installed with customised instance names, so that the 
> "default app" namespace lookup doesn't return anything, and Django must 
> fallback to the `current_app` to determine which app is being reversed?


 An app doesn't necessarily have to use its own patterns. With that said, 
it's up to the user to make sure it works if they are to mess with the 
app_name. Two conflicting apps can be installed with different namespaces, 
but there will always be a default (the last one, if there is no namespace 
with the same name). With a consistent use of `current_app` (even if it's 
not the *current* application used in the request), you can avoid problems. 

If possible, I'd like to add `current_app` to the request by default, but 
that has been attempted before, and backwards compatibility is a problem. 
That would allow an app to more reliably reverse its own urls, provided 
that their code and templates are called from within their own application. 

I'd rather see the "app name, period" (as opposed to a default app name) 
> defined as a variable in an app's URLconf as per #11642 or as an attribute 
> of the `urlpatterns` object, that Django looks at when a URLconf is 
> included with a dotted path string, instead of requiring users to import 
> and then include a `(patterns, app_name)` tuple. Basically, the app name 
> defined by the app should be used for both of:
>
 

include(r^foo/', 'foo.urls')
>
 

and
>
 

from foo.urls import some_tuple
> include(r'^foo/', some_tuple),


I also prefer the first option. That would be the "main" way of setting the 
app_name. The second option exists for things like `admin.site.urls`, which 
historically have always returned a tuple, instead of an object with an 
`urlpatterns` attribute. If objects like `admin.site` would have 
`urlpatterns` and `app_name` attributes/properties, this could be 
deprecated in favour of a single way to provide an app_name. Not sure if 
this is desirable, but it's an option. 

Not exactly related to the issue at hand, but if we are reworking URL 
> namespaces it might be worth some consideration. One reason why I always 
> avoid using URL namespaces these days is that it becomes impossible to 
> override an app URL at the project level. Project authors are stuck with 
> the exact URLs defined by the app author, all located below the same root 
> path where the URLs are included and with the same view behaviour.
>
 

Without namespaced URLs, the project author can include their own version 
> of a URL at any location (as long as it comes before the app's included 
> URLs) and change the view behaviour. For namespaced URLs, I'd like to be 
> able to do something like:
>
 

urlpatterns = patterns('',
>     url(r'^my_foo_login/$', 'myapp.views.my_foo_login', name='login', 
> app='foo', namespace='foo'),
>     url(r'^foo/', include('foo.urls', app='foo', namespace='foo')),
> )
>
 

Then when templates or view code in the `foo` app does reverse('foo:login') 
> they will get `/my_foo_login/` instead of `/foo/login/` and I can change 
> the behaviour of the view.


Now that's something I hadn't thought about. I don't believe there is an 
easy solution, at least not with the current API, so this will probably 
have to wait for the new API. I'll make sure to think this through, and 
find a way to handle this before I start working on the final 
implementation. 

Marten

Op vrijdag 29 mei 2015 02:52:24 UTC+2 schreef Tai Lee:
>
> Thanks for taking the time to write up this proposal. I agree on pretty 
> much all counts, but I do have a few comments:
>
> 1)
>
> If an app has templates and view code that are reversing 
> <app_name>:<view_name>, then changing the app name (e.g. by an undocumented 
> feature, passing a (patterns, app_name) tuple), then all those URLs will 
> break. Unless I'm missing something, an app *must always* be installed with 
> the app name that is hard coded in its templates and view code, so there is 
> no workaround for app namespace conflicts?
>
> Does or would it work to allow two apps with the same app namespace, as 
> long as they both are installed with customised instance names, so that the 
> "default app" namespace lookup doesn't return anything, and Django must 
> fallback to the `current_app` to determine which app is being reversed?
>
> 2)
>
> I'd rather see the "app name, period" (as opposed to a default app name) 
> defined as a variable in an app's URLconf as per #11642 or as an attribute 
> of the `urlpatterns` object, that Django looks at when a URLconf is 
> included with a dotted path string, instead of requiring users to import 
> and then include a `(patterns, app_name)` tuple. Basically, the app name 
> defined by the app should be used for both of:
>
> include(r^foo/', 'foo.urls')
>
> and
>
> from foo.urls import some_tuple
> include(r'^foo/', some_tuple),
>
> 3)
>
> Not exactly related to the issue at hand, but if we are reworking URL 
> namespaces it might be worth some consideration. One reason why I always 
> avoid using URL namespaces these days is that it becomes impossible to 
> override an app URL at the project level. Project authors are stuck with 
> the exact URLs defined by the app author, all located below the same root 
> path where the URLs are included and with the same view behaviour.
>
> Without namespaced URLs, the project author can include their own version 
> of a URL at any location (as long as it comes before the app's included 
> URLs) and change the view behaviour. For namespaced URLs, I'd like to be 
> able to do something like:
>
> urlpatterns = patterns('',
>     url(r'^my_foo_login/$', 'myapp.views.my_foo_login', name='login', 
> app='foo', namespace='foo'),
>     url(r'^foo/', include('foo.urls', app='foo', namespace='foo')),
> )
>
> Then when templates or view code in the `foo` app does 
> reverse('foo:login') they will get `/my_foo_login/` instead of 
> `/foo/login/` and I can change the behaviour of the view.
>
> Cheers.
> Tai.
>
>
> On Friday, May 29, 2015 at 1:21:58 AM UTC+10, Marten Kenbeek wrote:
>>
>> Sure, I'll go through the list of url tickets on Trac. 
>>
>> The key difference with #11642 is "default". What I propose is that 
>> urls.py specifies the app_name, period. The only reason to change app_name 
>> is conflicting app names, and there are easy workarounds that I feel 
>> shouldn't be part of the API itself. The namespace would be specified in 
>> include(), and default to the app_name. 
>>
>> Op donderdag 28 mei 2015 15:37:20 UTC+2 schreef Tim Graham:
>>>
>>> Point 1 sounds like https://code.djangoproject.com/ticket/11642 -- and 
>>> that ticket says it may be superseded by 
>>> https://code.djangoproject.com/ticket/21927. Could you review those 
>>> tickets as well as the others in the "Core (URLs)" component of Trac? It 
>>> would be good if you could assign yourself any tickets that your project 
>>> will address.
>>>
>>> On Wednesday, May 27, 2015 at 5:58:00 PM UTC-4, Marten Kenbeek wrote:
>>>>
>>>> Hi all,
>>>>
>>>> URL namespaces have a few quirks that make them a bit difficult to use 
>>>> and understand. I hope to create a patch that clears up these issues. 
>>>>
>>>> First up: the distinction between an application namespace and an 
>>>> instance namespace. The docs say on the application namespace:
>>>>
>>>> This describes the name of the application that is being deployed. 
>>>>> Every instance of a single application will have the same application 
>>>>> namespace.
>>>>
>>>>
>>>> And on the instance namespace: 
>>>>
>>>> This identifies a specific instance of an application. Instance 
>>>>> namespaces should be unique across your entire project. However, an 
>>>>> instance namespace can be the same as the application namespace. This is 
>>>>> used to specify a default instance of an application. 
>>>>
>>>>
>>>> The current implementation requires that both are specified in the same 
>>>> place: either in the included url configuration by returning a 3-tuple, or 
>>>> in the including url configuration through the arguments to include(). The 
>>>> first case generally does not allow multiple deployments of the same app, 
>>>> unless the included url configuration contains specific logic to return 
>>>> different instance namespaces. The second case does not in any way enforce 
>>>> that multiple deployments in fact have the same application namespace. 
>>>>
>>>> I'd like to get the semantics and the implementation in line, and 
>>>> provide one obvious way to specify namespaces. Including a set of url 
>>>> patterns under a namespace involves two parts: the including urlconf that 
>>>> calls include(), and the included urlconf that is imported by include(). 
>>>> The first is a specific deployment of the imported urlconf; the second is 
>>>> a 
>>>> single app. 
>>>>
>>>> The obvious way as I see it would be to specify the application 
>>>> namespace in the app, and specify the instance namespace as a parameter to 
>>>> include(). This enforces the single application namespace for a single set 
>>>> of patterns, and allows any end-user to specify the instance namespace on 
>>>> a 
>>>> per-instance basis. To take the admin as an example:
>>>>
>>>> admin.site.urls would return a 2-tuple: (patterns, 'admin'), where 
>>>> 'admin' is the application namespace. (An alternative to a 2-tuple could 
>>>> be 
>>>> an object with urlpatterns and app_name attributes.)
>>>> To include the admin instance, use include(admin.site.urls, 
>>>> namespace='admin'). This is the instance namespace. If left out, it could 
>>>> default to be the same as the app name.
>>>>
>>>> After a deprecation period, it would be an error to specify an instance 
>>>> namespace if there is no application namespace. This is to ensure that the 
>>>> app can always reverse its own urls using <app_name>:<view_name> if it 
>>>> specifies an application namespace, and using <view_name> if it doesn't. 
>>>> (Setting and app_name would technically still be possible by passing a 
>>>> hardcoded (patterns, app_name) tuple, just not as an advertised feature.)
>>>>
>>>> The second point is about nested namespace handling and current_app. 
>>>>
>>>> At the moment, current_app is looking for an exact namespace match. 
>>>> Unlike the namespaced view path, it is not split into namespace parts 
>>>> using 
>>>> current_app.split(':'). Take the following (fictional) urlpatterns:
>>>>
>>>> blog_patterns = [
>>>>     url(r'^comments-one/', include('comments.urls', 'comments-one', 
>>>> 'comments')),
>>>>     url(r'^comments-two/', include('comments.urls', 'comments-two', 
>>>> 'comments')),
>>>> ]
>>>>
>>>> urlpatterns = [
>>>>     url(r'^blog-one/', include(blog_patterns, 'blog-one', 'blog')),
>>>>     url(r'^blog-two/', include(blog_patterns, 'blog-two', 'blog')),
>>>> ]
>>>>
>>>> Because of how current_app is handled, it is now impossible to reverse 
>>>> patterns in 'blog-one:comments-one:' using current_app. To select 
>>>> 'blog-one', the current app needs to be the string 'blog-one', but to 
>>>> select 'comments-one', it needs to be 'comments-one'. The only solution is 
>>>> to hardcode at least one of the instance namespaces in the namespaced view 
>>>> path. This also means that setting request.current_app to 
>>>> request.resolver_match.namespace, as recommended in the docs, does not 
>>>> work 
>>>> if you have nested namespaces. 
>>>>
>>>> The ResolverMatch object also has some inconsistent behaviour for 
>>>> app_name. resolver_match.namespace is the full namespace path, i.e. 
>>>> 'blog-one:comments-one' (with resolver_match.namespaces a list of 
>>>> individual namespaces, i.e. ['blog-one', 'comments-one']), but 
>>>> resolver_match.app_name is the outer-most app_name, in this case 
>>>> 'blog-one', with no trace whatsoever of the full app_name path. 
>>>>
>>>> To illustrate how I would see it end up eventually (after the 
>>>> deprecation cycle), I've created a branch at 
>>>> https://github.com/knbk/django/tree/namespaces. I feel these changes 
>>>> are fairly straightforward, but any comments are appreciated. 
>>>>
>>>> Marten
>>>>
>>>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/c1f90515-d550-4993-83d5-57b2b898797f%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to