Django: 命名URL / 相同模板,不同命名URL

4

当点击相应链接时,我的Web应用程序会列出所有的艺术家、专辑和歌曲。我广泛使用通用视图(object_list/detail)和命名URL,但是我遇到了一个麻烦。我有三个模板,几乎输出完全相同的HTML,就像这样:

{% extends "base.html" %}
{% block content %}
<div id="content">

<ul id="starts-with">
{% for starts_with in starts_with_list %}
    <li><a href="{% url song_list_x starts_with %}">{{ starts_with|upper }}</a></li>
{% endfor %}
</ul>

<ul>
{% for song in songs_list %}
    <li>{{ song.title }}</li>
{% endfor %}
</ul>

</div>
{% endblock content %}

我的艺术家和专辑模板看起来几乎一样,我想把这三个模板合并成一个。我的变量以song开头的事实可以很容易地更改为默认的obj。问题是我不知道如何更正<ul id="starts-with">命名的URL。显然,我希望它使用我的urls.py中的命名URL链接到特定的专辑/艺术家/歌曲,但我不知道如何使其具有上下文感知能力。有什么建议吗? urls.py:
urlpatterns = patterns('tlkmusic.apps.tlkmusic_base.views',
    # (r'^$', index),
    url(r'^artists/$', artist_list, name='artist_list'),
    url(r'^artists/(?P<starts_with>\w)/$', artist_list, name='artist_list_x'),
    url(r'^artist/(?P<artist_id>\d+)/$', artist_detail, name='artist_detail'),
    url(r'^albums/$', album_list, name='album_list'),
    url(r'^albums/(?P<starts_with>\w)/$', album_list, name='album_list_x'),
    url(r'^album/(?P<album_id>\w)/$', album_detail, name='album_detail'),
    url(r'^songs/$', song_list, name='song_list'),
    url(r'^songs/(?P<starts_with>\w)/$', song_list, name='song_list_x'),
    url(r'^song/(?P<song_id>\w)/$', song_detail, name='song_detail'),
)
1个回答

3
您可以为通用的object_type定义URL模式,而不是为艺术家、专辑和歌曲分别定义。
urlpatterns = patterns('tlkmusic.apps.tlkmusic_base.views',
    # (r'^$', index),
    url(r'^(?P<object_type>\w+)/$', music_object_list, name='music_object_list'),
    url(r'^(?P<object_type>\w+)/(?P<starts_with>\w)/$', music_object_list, name='music_object_list_x'),
    url(r'^(?P<object_type>\w+)/(?P<object_id>\d+)/$', music_object_detail, name='music_object_detail'),

)

然后在您的模板中,您的url标签变成

{% url music_object_list_x object_type starts_with %} *

您可能只需要一个视图music_object_list。如果您发现不同对象类型需要不同的功能,则在music_object_list中调用各个函数。

def music_object_list(request, object_type, starts_with=None):
     if object_type == 'artists':
         return artist_list(request, starts_with=starts_with)
     elif object_type == 'albums':
         return album_list(request, starts_with=starts_with)
     ...

如果你正在使用 django.views.generic.list_detail.object_list,请记得在 extra_context 字典中添加 object_type。这将把 object_type 添加到模板上下文中,使 url 标签能够正常工作。

extra_context = {'object_type': 'songs', ...}

* 这是Django 1.2的新URL标签语法。对于旧版本,您需要使用逗号。
{% url music_object_list_x object_type,starts_with %}

查看文档(当前版本1.1版)以获取更多信息。

1
我喜欢这个方向!我正在尝试边说边看它是如何工作的。如果按计划进行,我将永远感激不尽。唯一需要改变的是使用 object_list 作为函数名似乎与 from django.views.generic.list_detail import object_list 冲突,但这很容易克服。我会回来分享我的发现! - TheLizardKing
关于名称冲突的问题很好。我已将该函数重命名为 music_object_list - Alasdair
我认为我在模板中使用{% url music_object_list_x object_type,starts_with %}时很难让它识别出object_type。我正在使用Django 1.1.1版本。 - TheLizardKing
哈哈,糟糕。我本应该添加我的视图,但现在通过传递extra_context = {'starts_with_list': starts_with_list, 'object_type': 'songs'}来解决了。 - TheLizardKing
不客气。我更新了我的答案,提到将 object_type 添加到 extra_context 中,但我看到你已经解决了! - Alasdair

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接