diff --git a/ietf/idrfc/idrfc_wrapper.py b/ietf/idrfc/idrfc_wrapper.py
index 66dab69ce..6d672f738 100644
--- a/ietf/idrfc/idrfc_wrapper.py
+++ b/ietf/idrfc/idrfc_wrapper.py
@@ -38,6 +38,8 @@ import re
from datetime import date
from django.utils import simplejson as json
from django.db.models import Q
+from django.db import models
+from django.core.urlresolvers import reverse
import types
BALLOT_ACTIVE_STATES = ['In Last Call',
@@ -198,11 +200,11 @@ class IdWrapper:
def friendly_state(self):
if self.draft_status == "RFC":
- return "RFC %d" % (self.rfc_number, self.rfc_number)
+ return "RFC %d" % (reverse('doc_view', args=['rfc%d' % self.rfc_number]), self.rfc_number)
elif self.draft_status == "Replaced":
rs = self.replaced_by()
if rs:
- return "Replaced by %s" % (rs[0],rs[0])
+ return "Replaced by %s" % (reverse('ipr_show', args=[rs[0]]),rs[0])
else:
return "Replaced"
elif self.draft_status == "Active":
@@ -357,8 +359,9 @@ class RfcWrapper:
# TODO: get AD name of the draft
return None
+ @models.permalink
def get_absolute_url(self):
- return "/doc/rfc%d/" % (self.rfc_number,)
+ return ('ietf.idrfc.views_doc.document_main', ['rfc%s' % (str(self.rfc_number))])
def displayname_with_link(self):
return 'RFC %d' % (self.get_absolute_url(), self.rfc_number)
diff --git a/ietf/idrfc/views_doc.py b/ietf/idrfc/views_doc.py
index 166467bc1..fc7b0d3e8 100644
--- a/ietf/idrfc/views_doc.py
+++ b/ietf/idrfc/views_doc.py
@@ -41,6 +41,7 @@ from django.template.defaultfilters import truncatewords_html
from django.utils import simplejson as json
from django.utils.decorators import decorator_from_middleware
from django.middleware.gzip import GZipMiddleware
+from django.core.urlresolvers import reverse
from ietf import settings
from ietf.idtracker.models import InternetDraft, IDInternal, BallotInfo, DocumentComment
@@ -189,7 +190,7 @@ def _get_history(doc, versions):
results.append({'is_text':True, 'date':doc._draft.expiration_date, 'text':'Draft expired'})
if doc.is_rfc_wrapper:
if doc.draft_name:
- text = 'RFC Published (see %s for earlier history)' % (doc.draft_name,doc.draft_name)
+ text = 'RFC Published (see %s for earlier history)' % (reverse('doc_view', args=[doc.draft_name]),doc.draft_name)
else:
text = 'RFC Published'
results.append({'is_text':True, 'date':doc.publication_date, 'text':text})
diff --git a/ietf/ipr/feeds.py b/ietf/ipr/feeds.py
index 476272768..4a1900302 100644
--- a/ietf/ipr/feeds.py
+++ b/ietf/ipr/feeds.py
@@ -3,12 +3,13 @@
from django.contrib.syndication.feeds import Feed
from django.utils.feedgenerator import Atom1Feed
from ietf.ipr.models import IprDetail
+from ietf.utils.lazy import reverse_lazy
from datetime import datetime, time
class LatestIprDisclosures(Feed):
feed_type = Atom1Feed
title = "IPR Disclosures to the IETF"
- link = "/ipr/"
+ link = reverse_lazy('ipr_showlist')
description = "Updates on new IPR Disclosures made to the IETF."
language = "en"
feed_url = "/feed/ipr/"
diff --git a/ietf/ipr/models.py b/ietf/ipr/models.py
index d25d78193..456f49af4 100644
--- a/ietf/ipr/models.py
+++ b/ietf/ipr/models.py
@@ -4,6 +4,7 @@ from django.db import models
#from django import newforms as forms
from ietf.idtracker.views import InternetDraft
from ietf.idtracker.models import Rfc
+from ietf.utils.lazy import reverse_lazy
# ------------------------------------------------------------------------
# Models
@@ -115,8 +116,9 @@ class IprDetail(models.Model):
return self.title
def docs(self):
return list(self.drafts.all()) + list(self.rfcs.all())
+ @models.permalink
def get_absolute_url(self):
- return "/ipr/%d/" % self.ipr_id
+ return ('ietf.ipr.views.show', [str(self.ipr_id)])
def get_submitter(self):
try:
return self.contact.get(contact_type=3)
diff --git a/ietf/ipr/urls.py b/ietf/ipr/urls.py
index 1e952d6b6..77a00f9a1 100644
--- a/ietf/ipr/urls.py
+++ b/ietf/ipr/urls.py
@@ -1,15 +1,16 @@
# Copyright The IETF Trust 2007, All Rights Reserved
-from django.conf.urls.defaults import patterns
+from django.conf.urls.defaults import patterns, url
from ietf.ipr import views, new, search
+from ietf.utils.lazy import reverse_lazy
from django.views.generic.simple import redirect_to
urlpatterns = patterns('',
- (r'^$', views.showlist),
+ url(r'^$', views.showlist, name='ipr_showlist'),
(r'^about/$', views.default),
(r'^by-draft/$', views.list_drafts),
- (r'^(?P\d+)/$', views.show),
- (r'^update/$', redirect_to, { 'url': '/ipr/' }),
+ url(r'^(?P\d+)/$', views.show, name='ipr_show'),
+ (r'^update/$', redirect_to, { 'url': reverse_lazy('ipr_showlist') }),
(r'^update/(?P\d+)/$', new.update),
(r'^new-(?Pspecific)/$', new.new),
(r'^new-(?Pgeneric)/$', new.new),
diff --git a/ietf/utils/lazy.py b/ietf/utils/lazy.py
new file mode 100644
index 000000000..dd31bd06c
--- /dev/null
+++ b/ietf/utils/lazy.py
@@ -0,0 +1,20 @@
+from django.utils.functional import lazy
+from django.core.urlresolvers import reverse
+
+"""
+A lazily evaluated version of `reverse()`_.
+
+It is useful for when you need to use a URL reversal before Django's
+URL names map is loaded. Some common cases where this method is necessary are:
+
+ * in your URL configuration (such as the ``url`` argument for the
+ ``django.views.generic.simple.redirect_to`` generic view).
+
+ * providing a reversed URL to a decorator (such as the ``login_url`` argument
+ for the ``django.contrib.auth.decorators.permission_required`` decorator).
+
+Usually unicode would be preference but str is the right type instead of unicode.
+This is because reverse passes through iri_to_uri which converts it to a string
+"""
+
+reverse_lazy = lazy(reverse, str)
diff --git a/ietf/utils/test_utils.py b/ietf/utils/test_utils.py
index 14461faf2..3e70a531b 100644
--- a/ietf/utils/test_utils.py
+++ b/ietf/utils/test_utils.py
@@ -215,3 +215,7 @@ def login_testing_unauthorized(tc, remote_user, url):
tc.client.login(remote_user=remote_user)
+class ReverseLazyTest(TestCase):
+ def test_redirect_with_lazy_reverse(self):
+ response = self.client.get('/ipr/update/')
+ self.assertRedirects(response, "/ipr/", status_code=301)