URL encoding, templates and apps: are apps not portlets?

79 views
Skip to first unread message

Alexandros Karypidis

unread,
Apr 1, 2012, 4:20:33 PM4/1/12
to django...@googlegroups.com
Hi,

My fondness of Python (while scripting things for work) grew to the point where I decided to try web development with it. Having (apparently) nothing better to do on a Sunday afternoon, I went through the Django tutorials.

The tutorial goes to some length to keep the "polls" app self-contained and easily embeddable into the mysite project. However, it seems to do so only for the back-end logic and not so much for the front-end UI.

In part 3 (https://docs.djangoproject.com/en/1.4/intro/tutorial03/#decoupling-the-urlconfs) it rewrites the URLConfs to "mount" the app under some site-specific prefix (/polls).

urlpatterns = patterns('',
    url(r'^polls/', include('polls.urls')),

I quote from the tutorial:

"The idea behind include() and URLconf decoupling is to make it easy to plug-and-play URLs. Now that polls are in their own URLconf, they can be placed under "/polls/", or under "/fun_polls/", or under "/content/polls/", or any other path root, and the app will still work."

Ironically, it does not seem to be bothered with the HTML side of things. Therefore:

1) index.html produces a hard-coded list of polls, which MUST be mounted at "/polls", with:
    {% for poll in latest_poll_list %}
        <li><a href="/polls/{{ poll.id }}/">{{ poll.question }}</a></li>
    {% endfor %}
2) detail.html routes the voting action to "/polls" POST
    <form action="/polls/{{ poll.id }}/vote/" method="post">
3) results.html takes you back to voting in "/polls"
    <a href="/polls/{{ poll.id }}/">Vote again?</a>

As I suspected, changing "mysite.urls" to this:

    urlpatterns = patterns('',
        url(r'^fun_polls/', include('polls.urls')),

... broke everything which was carefully crafted on the application-code side of things.

I am currently tinkering to define a "app_prefix" variable in the code and trying to have the templates read it from the context, so that things become more modular...

I thought apps in Django were supposed to be like "Wicket components" or "Java portlets" (i.e. carry their UI along). Am I letting my Java background take me to the wrong direction here? Obviously, if someone were to use the polls code mounted under "/fun_polls" they could create their own version of "index/details/results.html" that use "/fun_polls" for their prefix (and even display things differently)...

Alexandros Karypidis

unread,
Apr 1, 2012, 5:23:31 PM4/1/12
to django...@googlegroups.com
So, having discovered how to extend the context of a generic view, I've now managed to make things a bit more self-contained:

1) In polls.urls add a name for the index page (just like for the 'poll_results' case)
--------------
urlpatterns = patterns('',
# ...
        name='poll_index'),
2) In polls.init create a module-wide utility-function to reverse the index url:
--------------
from django.core.urlresolvers import reverse
def get_polls_prefix():
    return reverse('poll_index').strip('/')

3) Subclass ListView/DetailsView to add a "prefix" value to the template context. For example (PollDetailsView is similar):
--------------
class PollListView(ListView):
    def get_context_data(self, **kwargs):
        context = super(PollListView, self).get_context_data(**kwargs)
        context['prefix'] = polls.get_polls_prefix()
        return context

urlpatterns = patterns('',
    url(r'^$',
        PollListView.as_view(
            queryset=Poll.objects.order_by('-pub_date')[:5],
            context_object_name='latest_poll_list',
            template_name='polls/index.html'),
        name='poll_index'),

4) Now, all my web pages use the prefix from the context; e.g. index.html looks like this:
--------------
....

    {% for poll in latest_poll_list %}
        <li><a href="/{{ prefix }}/{{ poll.id }}/">{{ poll.question }}</a></li>
    {% endfor %}
--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django...@googlegroups.com.
To unsubscribe from this group, send email to django-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

Tom Evans

unread,
Apr 2, 2012, 5:21:57 AM4/2/12
to django...@googlegroups.com

The tutorial is just omitting some common steps to make it simpler,
which at the same time makes it less resilient and correct.

When you setup your urlconf, you should explicitly name each URL:

urlpatterns = patterns('',
url(r'^$', 'foo.homepage', name='homepage'),
url(r'^about$', 'foo.about', name='about'),
url(r'^polls/(?P<poll_id>\d+)$', 'polls.view_poll', name='view_poll'),
)

Then, in your templates, you refer to the URLs by name, and ask Django
to sort out what the URL is:

{% for poll in polls %}
<li><a href="{% url view_poll poll.id %}">{{ poll }}</a></li>
{% endfor %}

Now, regardless of how the urlconf is tweaked, the generated HTML will
always be correct.

See the docs:

https://docs.djangoproject.com/en/1.4/topics/http/urls/#id2
https://docs.djangoproject.com/en/1.4/ref/templates/builtins/#url

Cheers

Tom

Reply all
Reply to author
Forward
0 new messages