Search code examples
djangodjango-urlsdjango-1.5url-patterndjango-formwizard

How do I change the view a URL resolves to after a certain date?


I'm writing a contest app. The contest closes at midnight on a particular date. I want to have the app automatically switch from: using a CookieWizardView, from formtools; to a normal TemplateView, from the generic view library.

Currently the relevant part of my urlpatterns looks like this:

urlpatterns += patterns('',
    url(r'^$', 'appname.views.contest'), # the CookieWizardView
)

and I'd like it, after a certain date, to act as though it looks like this:

urlpatterns += patterns('',
    url(r'^$', 'appname.views.contestclosed'), # a TemplateView
)

I am totally, totally fine with having a hard-coded magic number, I just don't want to be up at midnight that day!

~~

I solved this but can't answer my own question because I'm too new.

I made a function in my views.py:

def contest_switcher(request):
    if datetime.datetime.now() < datetime.datetime(YEAR_OVER, MONTH_OVER, DAY_OVER):
        return contest(request)
    else:
        return contestclosed(request)

This does the trick, now my urlpattern is:

urlpatterns += patterns('',
    url(r'^$', 'appname.views.contest_switcher'),
)

I did have to add a function to my contest closed view, though, because it wasn't expecting a POST, which could happen if someone is trying to fill out the contest form at midnight:

class ContestClosedView(TemplateView):
    template_name = "appname/closed.html"

    def post(self, *args, **kwargs):
        return self.get(*args, **kwargs)

contestclosed = ContestClosedView.as_view()

Solution

  • You don't have to try to hack your urls.py to pull this off. Set one URL pattern that points to a view that looks like this:

    def contest_page(request, contest_id):
        try:
            contest = Contest.objects.get(pk=contest_id)
        except Contest.DoesNotExist:
            raise Http404  # minimum necessary - you can do better
        if datetime.datetime.now() < contest.end_date:  # model field rather than module constants
            return contest(request, contest_id)  # CookieWizardView
        else:
            return contestclosed(request, contest_id)  # TemplateView
    

    This is basically your contest_switcher with improvements:

    • Applies to multiple contests
    • Contests know their own end date so you don't clutter your module scope with constants
    • Simple urls.py and the view does the work of delegating what is shown (you know, the view)

    (Note that this example implies that you would change your models correspondingly and import all the correct libraries and such.)