4

Given two categories of entities, I'm selecting some kind of cross product set of them with the following URL definition:

url(r"^category1/(?P<category1>([0123456789]+,?)+)/category2(?P<category2>([0123456789]+,?)+)/$", view, {}, name="cross")

so basically URLs like /category1/1,2,3,4/category2/5,6,7,8/ are valid.

Now I introduced several views onto the same data, so that now I have URLs like /category1/1,2,3,4/category2/5,6,7,8/view1/ and /category1/1,2,3,4/category2/5,6,7,8/view2/. I would like to redirect the "old" URLs to view1. I haven't found anything easier than this:

url(r"^category1/(?P<category1>([0123456789]+,?)+)/category2(?P<category2>([0123456789]+,?)+)/$",
    redirect_to, {
    'url': lazy(lambda: reverse(
        'cross_view1',
        kwargs={
            'category1': '111111',
            'category2': '222222',
        }
     ).replace('111111', '%(category1)s') \
      .replace('222222', '%(category2)s'), str)(),
     name="cross"}

The point here is that I want to reuse my matched groups in the URL, however, I cannot give them as kwargs to redirect_to, since they wouldn't be interpolated, and neither can I put verbatim formatting in the URL since it has to match my regex (comma-separated numeric IDs). So I introduce some unique ID (111111 and 222222 in this case) and replace them afterwards.

Obviously this feels, looks, smells and tastes very hacky. Is there any cleaner way to do this, apart from introducing an additional view and skipping redirect_to altogether?

AstroCB
  • 12,337
  • 20
  • 57
  • 73
Nikolai Prokoschenko
  • 8,465
  • 11
  • 58
  • 97
  • Got to ask (I'm new to Django: most of my python work was in Turbogears), but why wouldn't `url(r"^category1/(?P([0123456789]+,?)+)/category2(?P([0123456789]+,?)+)/$", redirect_to, {'url': '/category1/%(category1)s/category2/%(category2)s/view1',})` work? – Femi Jun 15 '11 at 16:36
  • 1
    @Femi: because I want to re-use my URL building scheme. If I ever change it (which is entirely possible at this stage), I wouldn't need to track down every place where I could have used URL concatenation. URL reversing is also supposed to be the "clean" way of Django development -- which is, as we see from the code, not completely obvious ;) – Nikolai Prokoschenko Jun 15 '11 at 16:48
  • Why is introducing an additional view out of the question? – André Caron Jun 15 '11 at 18:54
  • 1
    @André Caron: it's not exactly out of question, I will probably have to introduce it anyway, however I'd like to know the quirks of using Django's shipped generic views and especially their connection to best practices promoted by and for Django. If using `redirect_to` with `reverse` means writing ugly code like the one I've written, then I won't bother using `redirect_to` apart from very simple cases. If there is another way, I'd like to learn about it -- hence this question. – Nikolai Prokoschenko Jun 15 '11 at 19:41
  • This looks like it might answer your question: http://stackoverflow.com/questions/15706489/redirect-to-named-url-pattern-directly-from-urls-py-in-django – Brenda J. Butler Jul 04 '13 at 17:03

2 Answers2

1

You have some options here. You can use RedirectView, but I was unable to get it to reverse urls, since it looks like it runs before urlpatterns loads up. You can use it like so, tailor this to be used in your project:

from django.views.generic import RedirectView

Add this to your urlpatterns:

url(r'^(?P<location_id>\d+)/$', RedirectView.as_view(url='/statistics/dailyreport/%(location_id)s/')),

USE LAMBDA: This should work in most versions of django, I am using it in 1.6.5:

from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
urlpatterns = patterns('',
    ....
    url(r'^(?P<location_id>\d+)/$', lambda x, location_id: HttpResponseRedirect(reverse('dailyreport_location', args=[location_id])), name='location_stats_redirect'),
    ....
)
radtek
  • 34,210
  • 11
  • 144
  • 111
0

Just a quick note that in your reg exp you can use [0-9] instead of [0123456789]

QuantumLicht
  • 2,103
  • 3
  • 23
  • 32