1

I am trying to use get_absolute_url to follow DRY rules. If I code the class to build the href directly from the slug it all works fine. Ugly, messy but working...

So I am trying to get this done right using get_absolute_url() and I am getting stuck with a NoReverseMatch exception using the code below. I know this must be some kind of newbie error, but I have been up and down all the docs and forums for days, and still can't figure this one out!

I get this error:

NoReverseMatch at /calendar
Reverse for 'pEventsCalendarDetail' with arguments '()' and keyword arguments '{u'slug': u'Test-12014-05-05'}' not found. 0 pattern(s) tried: []
Request Method: GET
Request URL:    http://127.0.0.1:8000/calendar
Django Version: 1.6
Exception Type: NoReverseMatch
Exception Value:    
Reverse for 'pEventsCalendarDetail' with arguments '()' and keyword arguments '{u'slug': u'Test-12014-05-05'}' not found. 0 pattern(s) tried: []
Exception Location: /usr/local/lib/python2.7/site-packages/django/core/urlresolvers.py in _reverse_with_prefix, line 429
Python Executable:  /usr/local/opt/python/bin/python2.7
Python Version: 2.7.6

using the following models.py excerpt:

@python_2_unicode_compatible
class Event(models.Model):
    eventName = models.CharField(max_length=40)
    eventDescription = models.TextField()
    eventDate = models.DateField()
    eventTime = models.TimeField()
    eventLocation = models.CharField(max_length=60, null=True, blank=True)
    creationDate = models.DateField(auto_now_add=True)
    eventURL = models.URLField(null=True, blank=True)
    slug = AutoSlugField(populate_from=lambda instance: instance.eventName + str(instance.eventDate),
                         unique_with=['eventDate'],
                         slugify=lambda value: value.replace(' ','-'))

    @models.permalink
    def get_absolute_url(self):
        from django.core.urlresolvers import reverse
        path = reverse('pEventsCalendarDetail', (), kwargs={'slug':self.slug})
        return "http://%s" % (path)

The complete urls.py file:

from django.conf.urls import patterns, include, url

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    # Examples:
    url(r'^$', 'electricphoenixfll.views.home', name='home'),
    url(r'^home$', 'electricphoenixfll.views.home', name='home'),
    url(r'^calendar$', 'electricphoenixfll.views.calendar', name='calendar'),
    url(r'^forum$', 'electricphoenixfll.views.forum', name='forum'),
    url(r'^donate$', 'electricphoenixfll.views.donate', name='donate'),
    url(r'^donate_thanks$', 'electricphoenixfll.views.donate_thanks', name='donate_thanks'),
    url(r'^what_is_fll$', 'electricphoenixfll.views.what_is_fll', name='what_is_fll'),
    url(r'^core_values$', 'electricphoenixfll.views.core_values', name='core_values'),
    url(r'^follow_the_phoenix$', 'electricphoenixfll.views.follow_the_phoenix', name='follow_the_phoenix'),
    url(r'^followEnter/$', 'electricphoenixfll.views.followEnter', name='followEnter'),
    url(r'^followList/$', 'electricphoenixfll.views.followList', name='followList'),
    url(r'^about_us$', 'electricphoenixfll.views.about_us', name='about_us'),
    url(r'^calendarDetail/(?P<slug>[\w-]+)/$', 'phoenixEvents.views.calendarDetail', name='pEventsCalendarDetail'),

    url(r'^admin/', include(admin.site.urls)),
)
Arana
  • 179
  • 1
  • 14

2 Answers2

1

The second positional argument to reverse() is urlconf argument:

reverse(viewname[, urlconf=None, args=None, kwargs=None, current_app=None])

To make it work use keyword argument for setting args:

path = reverse('pEventsCalendarDetail', args=(), kwargs={'slug':self.slug})

Or, don't set args at all:

path = reverse('pEventsCalendarDetail', kwargs={'slug':self.slug})
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
  • Thank you!! I thought the name provided the reference to the urlconf info. Isn't that what I am specifying in the urls.py file? Wouldn't adding that into a call to reverse() be imbedding the url into another place in the code... That only leaves me with the missing 'domain' portion of the url. Is there should I get that from os.path or is there a more Django-ish way to get that? – Arana May 20 '14 at 00:11
  • @Arana did it help? Django finds your `urls.py` files automatically, no need to specify `urlconf` argument manually. Unless you are doing smth "outside of the box". – alecxe May 20 '14 at 00:14
  • Yes, it certainly did! Sorry, I wasn't clearer about that. What I have now is missing the domain (Test 1) What is best way to add that last portion? – Arana May 20 '14 at 00:35
  • I know it finds my urls.py automatically, that is why I was questioning the 'need' for a parameter in reverse() that would specify urlconf. Is it a leftover from an older version, or is there another reason I would want to use it? (Just trying to learn more...) – Arana May 20 '14 at 00:39
  • @Arana Ok, thanks, take a look http://stackoverflow.com/questions/2345708/how-can-i-get-the-full-absolute-url-with-domain-in-django. – alecxe May 20 '14 at 00:43
  • @Arana you would use `urlconf` argument when your `urls` are defined in a custom place, not in `urls.py`, for example. It is just a hint for Django to reverse based on the specified path to the custom `urls.py`. – alecxe May 20 '14 at 00:45
  • Thanks for all the help Alec. I'll read that post again. Now I should be able to make more sense out of it! – Arana May 20 '14 at 01:36
  • One final comment for anyone that is looking for the FINAL answer on how to build the full url. I did cheat a bit by adding the port number to the initial domain name, but once I'm on a production server the port number will be the default port 80. def get_absolute_url(self): from django.contrib.sites.models import Site from django.core.urlresolvers import reverse path = reverse('pEventsCalendarDetail', kwargs={'slug':self.slug}) return "http://%s%s" % (Site.objects.get_current().domain, path) – Arana May 20 '14 at 02:34
1

Don't use both the permalink decorator and the reverse() call. They both do the same thing. Drop the decorator: it is deprecated.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895