Hi all, Full disclosure: I’m one of the authors of django-hosts. But I’ve thought about this problem a lot and maybe that’s useful for this discussion, maybe not :)
# Passing the request to reverse I'm not convinced that reverse should be directly passed the request to build a full URL since it removes the separation of concern between request parameter handling and URL reversal and therefore be a step in the wrong direction. Having to hand around the request on application level is basically a waste of CPU cycles since that information is already be known to Django on the URL resolver level. Of course I acknowledge that the use case of generating full URLs on application level exists and that there are multiple ways to achieve this goal. E.g. django-hosts has been designed to mimic the URL pattern system to follow a recognizable and well-established pattern outside of Django’s core, and does more than just single-host reversal. # django-hosts It allows a single Django project to respond to requests with different HTTP_HOST headers (e.g. docs.example.com, api.example.com, admin.example.com) and maps each host to different URL configurations if configured so in "host patterns”, conventionally defined in hosts.py next to a project’s urls.py. Since it was developed as a 3rd party app it obviously had to implement its own reverse method to take the host into account when doing the reversal, since the actual lookup happens with the predefined host patterns, while the URL path reversal happens with Django’s own reverse. It uses a ROOT_HOSTCONF setting to locate the host patterns (similar to ROOT_URL) and defaults to the host that is defined by the DEFAULT_HOST setting if not provided during the reversal. That way it is API-compatible when used via its reverse function or template tag. I wasn't around when the inclusion of django-hosts or similar ideas was discussed at the DuTH sprint so I’m not sure how much of django-hosts can and should be ported to Django. I let Tim elaborate on that. # Hosts in Django What I personally would see as the right direction is to find a common ground for apps like django-hosts and simpler use cases such as generating the full URL when reversing a URL. From a user perspective I like where the DEP (https://github.com/django/deps/pull/27) for simpler URL patterns goes, e.g. it proposes something like this: urlpatterns = [ path('articles/2003/', views.special_case_2003), path('articles/<int:year>/', views.year_archive), path('articles/<int:year>/<int:month>/', views.month_archive), path('articles/<int:year>/<int:month>/<int:day>/', views.article_detail), ] So what we could do is allow optionally wrapping some paths with a new, optional host function: from django.urls import path, host urlpatterns = [ host('blog.example.com', [ path('articles/2003/', views.special_case_2003, name='blog-special-2003'), path('articles/<int:year>/', views.year_archive, name='blog-year'), path('articles/<int:year>/<int:month>/', views.month_archive, name='blog-month'), path('articles/<int:year>/<int:month>/<int:day>/', views.article_detail, name='blog-day'), ], scheme='//'), host('api.example.com', [ path('v1/', include(api.urls), namespace='api'), ], scheme='https://') ] The host function adds the given host and optional scheme to each URL pattern so it's available in the URL resolver reverse function as an optional parameter when constructing the URL. Of course that also means that the URL resolver requires the request host when it resolves the URL pattern callback and not only the request path. But since that’s an internal API I don’t see any backward-compatibility issues with that. Both the main reverse function and the URL tag would simply get new parameters whether or not to return the full URL (defaulting to False for backward compatibility) and maybe an optional scheme parameter. All those would be possible calls: reverse('blog-year', kwargs={'year': 2016}) -> /articles/2016/ reverse('blog-year', kwargs={'year': 2016}, host=True) -> //blog.example.com/articles/2016/ reverse('blog-year', kwargs={'year': 2016}, host=True, scheme='https://') -> https://blog.example.com/articles/2016/ reverse('api:user-list') -> /v1/users/ reverse('api:user-list', host=True) -> https://api.example.com/v1/users/ reverse('api:user-list', host=True, scheme='//') -> //api.example.com/v1/users/ {% url 'blog-year' year=2016 %} -> /articles/2016/ {% url 'blog-year' year=2016 with host=True %} -> //blog.example.com/articles/2016/ {% url 'blog-year' year=2016 with host=True scheme='https://' %} -> https://blog.example.com/articles/2016/ {% url 'api:user-list' %} -> /articles/2016/ {% url 'api:user-list' with host=True %} -> https://api.example.com/v1/users/ {% url 'api:user-list' with host=True scheme='//' %} -> //api.example.com/v1/users/ Tim, does that follow your ideas about adding django-hosts like features to Django? Jannis > On 11 Nov 2016, at 09:14, Mislav Cimperšak <mislav.cimper...@gmail.com> wrote: > > Thinking about url tag and threadlocals is a step in the wrong direction. > > The original PR is just a simple addition (that is still backwards > compatible) to the `reverse` method; how people choose to use it (and when) > is up to them. Adding something to the `url` tag is almost bound to brake > something. > This implementation does not brake anything regarding `url` tag and can stand > on it's own. > > I've talked to several people on sprints in Amsterdam before submitting a PR > and it sounded like a good idea to them and reassured with DRF implementation > I went with it :) > > On Sat, Nov 5, 2016 at 11:04 PM, Florian Apolloner <f.apollo...@gmail.com> > wrote: > On Saturday, November 5, 2016 at 6:56:29 PM UTC+1, Sjoerd Job Postmus wrote: > If you go with storing the base domain in the threadlocals, why not go full > in and store the request itself in the locals? [1] > > > Because that opens a whole new can of worms, if possible we want less > threadlocals, not more… > > As far as using it in the templates... We have a RequestContext right? So in > most cases that should not be an issue I presume. > > > Still leaves the question of how to nicely pass this to the url tag. > > But yes, Celery would be a problem, unless we push the request object to > celery as well, but I presume that makes mostly no sense except for this. > > > Yeah, I didn't think that through :) > > -- > You received this message because you are subscribed to a topic in the Google > Groups "Django developers (Contributions to Django itself)" group. > To unsubscribe from this topic, visit > https://groups.google.com/d/topic/django-developers/-rbLcdJkIpk/unsubscribe. > To unsubscribe from this group and all its topics, 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 https://groups.google.com/group/django-developers. > To view this discussion on the web visit > https://groups.google.com/d/msgid/django-developers/84fc3b7a-4263-46bb-a292-e27215952e63%40googlegroups.com. > > For more options, visit https://groups.google.com/d/optout. > > > -- > 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 https://groups.google.com/group/django-developers. > To view this discussion on the web visit > https://groups.google.com/d/msgid/django-developers/CACcAD09g-yCWw6U5WS-ykKJRG5poWnrBCEOTGFO6YrQKgCKePQ%40mail.gmail.com. > For more options, visit https://groups.google.com/d/optout. -- 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 https://groups.google.com/group/django-developers. To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/C508621B-9931-463D-86F3-205824A366CE%40gmail.com. For more options, visit https://groups.google.com/d/optout.