Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django No Reverse Match with Arguments

From my template:

<a href="{% url 'tracker:othermonth' year next_month %}">July</a>

URL Pattern:

url(r'^ocal/$', views.calendar, name = "othermonth"),

View:

def calendar(request, year, month):
    my_year = int(year)
    my_month = int(month)
    my_calendar_from_month = datetime(my_year, my_month, 1)
    my_calendar_to_month = datetime(my_year, my_month, monthrange(my_year, my_month)[1])

    my_tickets = Event.objects.filter(on_sale__gte=my_calendar_from_month).filter(on_sale__lte=my_calendar_to_month)

    my_previous_year = my_year
    my_previous_month = my_month - 1
    if my_previous_month == 0:
        my_previous_year = my_year - 1
        my_previous_month = 12
    my_next_year = my_year
    my_next_month = my_month + 1
    if my_next_month == 13:
        my_next_year = my_year + 1
        my_next_month = 1
    my_year_after_this = my_year + 1
    my_year_before_this = my_year - 1

    cal = TicketCalendar(my_tickets).formatmonth(year, month)

    return render_to_response('calendar.html', {'events_list': my_tickets,
                                                'calendar': mark_safe(cal),
                                                'month': my_month,
                                                'month_name': named_month(my_month),
                                                'year': my_year,
                                                'previous_month': my_previous_month,
                                                'previous_month_name': named_month(my_previous_month),
                                                'previous_year': my_previous_year,
                                                'next_month': my_next_month,
                                                'next_month_name': named_month(my_next_month),
                                                'next_year': my_next_year,
                                                'year_before_this': my_year_before_this,
                                                'year_after_this': my_year_after_this,
    }, context_instance=RequestContext(request))

Error:

Reverse for 'othermonth' with arguments '(2013, 7)' and keyword arguments '{}' not found.

I've searched through stackoverflow and the django documentation but I can't seem to figure out why I'm getting this NoReverseMatch error. I'm sure its a very simple oversight on my part because I'm staring at code from a previous project which is almost identical to this and that works fine. Any help would be appreciated, thanks.

UPDATE: I tried removing the parameters that I was trying to send with the URL and that fixed the NoReverseMatch however the view that is called requires those arguments so the link fails.

like image 980
apardes Avatar asked Jun 19 '13 23:06

apardes


1 Answers

How do you plan for those arguments to be embedded in your URL? There's nothing capturing them, and no way for the reverse lookup to construct it. You need a URL pattern that accepts these parameters. Something like:

url(r'^ocal/(?P<year>\d{4})/(?P<month>(0|1)?\d)/$', views.calendar, name = "othermonth_bymonth"),

Using keyword rather than positional arguments here is optional, but I think it makes things easier - and allows setting default values that can trigger behavior like showing a calendar for the current day when nothing's specified.

Also, your mytickets queryset can also be constructed thus:

mytickets = Event.objects.filter(on_sale__year=year, onsale__month=month)

Which I think is a little cleaner to read.

Actually, upon a closer look - Django's built in date based views can do a lot of this for you. If you haven't already looked into them, I recommend doing so:

https://docs.djangoproject.com/en/dev/ref/class-based-views/generic-date-based/

For this particular view, all you'd need to do is subclass MonthArchiveView to create your TicketCalendar instance and add it to your context.

Edit: OK, you're still getting problems. This is how I would go about solving this:

views.py
class TicketMonthArchiveView(MonthArchiveView):
    allow_empty = True # show months even in which no tickets exist
    allow_future = True # show future months
    model = Event

    def get_context_data(self, **kwargs):
        base_context = super(TicketMonthArchiveView, self).get_context_data(**kwargs)
        my_tickets = kwargs['object_list']
        base_context['calendar'] = mark_safe(TicketCalendar(my_tickets).formatmonth(self.get_year(), self.get_month()))
        # the above could be a little off because I don't know exactly how your formatmonth method works
        return base_context

urls.py
    from somewhere.views import TicketMonthArchiveView
    # other patterns, plus:
    url(r'^ocal/(?P<year>\d{4})/(?P<month>(0|1)?\d)/$', TicketMonthArchiveView.as_view(), name='calendar_by_month'),

template event_archive_month.html
    <a href="{% url 'tracker:calendar_by_month' next_month|date:'%Y' next_month|date:'%m' %}">{{ next_month|date:'%f' }}</a>

Obviously there's a lot more you could do here with the year and day views, but this should demonstrate the general concepts.

like image 121
Peter DeGlopper Avatar answered Sep 19 '22 22:09

Peter DeGlopper