Django:命名网址 / 同一模板,不同命名网址

4 投票
1 回答
742 浏览
提问于 2025-04-15 21:44

我有一个网页应用,当点击相应的链接时,会列出我所有的艺术家、专辑和歌曲。我大量使用了通用视图(比如对象列表和详细信息)和命名的链接,但遇到了一些麻烦。我有三个模板,它们输出的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"> 的命名链接。显然,我想让它链接到特定的专辑、艺术家或歌曲,使用我在 urls.py 中定义的命名链接,但我不知道怎么让它根据上下文来识别。有什么建议吗?

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

你可以为一个通用的对象类型定义网址模式,而不是单独为艺术家、专辑和歌曲定义:

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 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,记得把 object_type 加入到 extra_context 字典中。这样可以把对象类型添加到模板上下文中,让网址标签正常工作。

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

* 这是Django 1.2的新网址标签语法。在旧版本中,你需要用逗号。

{% url music_object_list_x object_type,starts_with %}

想了解更多信息,可以查看文档(当前版本, 1.1版本

撰写回答