返回介绍

Dynamic URL

发布于 2025-02-27 00:22:13 字数 7133 浏览 0 评论 0 收藏 0

除了在首页显示文章的摘要外,通常也会希望每篇文章能有独立的网址与页面。例如,我们可能会希望 http://127.0.0.1/post/3/ 能够是 pk 为 3 那篇文章的网址,而页面内容则是此篇日记的详细资讯,而非摘要。

在这个章节,我们会学到如何设定动态网址的 URL conf,让每篇旅游日记,拥有独一无二的网址与页面。

建立单篇文章的 View

首先建立单篇文章所使用的 view function。在 trips/views.py 中,新增 post_detail 这个 view 如下:

# trips/views.py

def post_detail(request, pk):
    post = Post.objects.get(pk=pk)
    return render(request, 'post.html', {'post': post})

以访客浏览 http://127.0.0.1:8000/post/3/ 的例子,来解释以上程式:

  • 目前浏览文章的 pk 会传入 view 中: 当访客浏览 http://127.0.0.1/post/3/ 时,传入 view 的 pk 会是 3。
    • URL 与 pk 的对应,会在稍后设定。这裡只需知道 view 中传入的,会是当前浏览文章 pk 即可。
  • 取得传入 pk 的那篇 Post 资料: 当传入的 pk=3,代表访客想看到 pk=3 那篇文章。我们可以利用之前学过的 ORM 语法 get , 取得该篇日记的 Post 物件:
      post = Post.objects.get(pk=pk)  # 此时 pk = 3
    
  • 回传 HttpResponse: 将取得的 post(pk=3)传入 Template post.html ,并呈现 render 后的结果。

设定动态网址的对应

日记单页的 view function 完成后,我们来设定网址与 view 的对应。修改 mysite/urls.py ,加入以下内容:

# mysite/urls.py
from trips.views import hello_world, home, post_detail

urlpatterns = [
    ...
    url(r'^post/(?P<pk>\d+)/$', post_detail, name='post_detail'),
]

上面的修改完成后,只要连至 http://127.0.0.1/post/3/ 就会对应到 post_detail() 这个 view,并且 传入的 pk=3

使用 Regex 提取部份 URL 为参数

我们前面提过,Django 的 URL 是一个 regular expression (regex) 。Regular expression 语法可用来描述一个字串的样式。 除了可以表示固定字串之外,还可以用来表示不确定的内容。我们一步一步解释文章单页所使用的 URL 设定:

(?P<pk>\d+)
  1. \d 代表一个阿拉伯数字。
  2. + 代表“一个以上”。

    所以 \d+ 代表一个以上的阿拉伯数字,例如“0”、“99”、“12345”。可是像“8a”就不符合,因为“a”不是数字。

  3. (?P<pk>) 代表“把这一串东西抓出来,命名为 pk。

    所以 (?P<pk>\d+) 代表:抓出一个以上阿拉伯数字,并把抓出来的东西取名为 pk。

综合以上的规则, r'^post/(?P<pk>\d+)/$' 会达成以下的效果:

URL符合结果
http://127.0.0.1/ posts/不符合,因为前面不是 post/ 开头。
http://127.0.0.1/ post/不符合,因为后面抓不到数字。
http://127.0.0.1/ post/1/符合,抓到的 pk 是 1。
http://127.0.0.1/ post/1234/符合,抓到的 pk 是 1234。
http://127.0.0.1/ post/12ab/不符合,因为后面有不是数字的东西。

建立单篇日记页的 Template

回顾一下前面写的 view function( post_detail )内容

return render(request, 'post.html', {'post': post})

我们取得所需 post 物件后,传入 post.html 这个 template 中 render。现在我们就来完成这个 template。建立 post.html 如下:

<!-- templates/post.html -->

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>{{ post.title }} | A Django Girl’s Adventure</title>
    <link href="//fonts.googleapis.com/css?family=Lemon" rel="stylesheet" type="text/css">
    <link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet" type="text/css">
    <link href="//djangogirlstaipei.github.io/assets/css/style.css" rel="stylesheet" type="text/css">
</head>
<body>
    <div class="header">
        <h1 class="site-title text-center">
            <a href="/">A Django Girl’s Adventure</a>
        </h1>
    </div>
    <div class="container post post-detail">
        <div class="post-heading">
            <h1 class="title"><a href="{% url 'post_detail' pk=post.pk %}">{{ post.title }}</a>
            </h1>
            <div class="date">{{ post.created_at|date:'Y / m / d' }}</div>
        </div>
        <div class="location">
            <i class="fa fa-map-marker"></i>
            <span id="location-content">{{ post.location }}</span>
        </div>
        <div id="map-canvas" class="map"></div>
        <div class="post-content">
            {{ post.content }}
        </div>
        <hr class="fancy-line">
        <img class="photo" src="{{ post.photo }}" alt="Cover photo for {{ post.title }}">
    </div>
    <script src="//maps.googleapis.com/maps/api/js?v=3.exp&libraries=places&sensor=false"></script>
    <script src="//djangogirlstaipei.github.io/assets/js/map.js"></script>
</body>
</html>

这个 template 将 post 物件的属性 (e.g. 标题、内文、时间......等),利用 {{ var }} 与 template filter 显示并格式化于 HTML 中。若资料库裡有 pk=3 的 Post,现在连至 http://127.0.0.1:8000/post/3/ 即可看到此日记的单页。

{% url %}

连结到特定 view 的 template tag

使用方法:

语法说明
{% url '<view_name>' %}根据在 urls.py 中设定的“name”值,找到对应的 URL

也可以传入参数,如:

{% url '<view_name>' arg1=<var1> arg2=<var2> ...%}

其馀用法可参考 官方文件

加入到单篇日记页的连结

最后,我们还需在首页加上单篇日记的连结。我们可以使用 {% url %} 这个 template tag 达成。需要加入的地方有:

  1. 每篇日记
  2. 每篇日记的 Read More 按钮

设定标题连结

打开 home.html ,找到下面的内容:

<!-- home.html -->

<h2 class="title">
    <a href="#">{{ post.title }}</a>
</h2>

将它改成

<!-- home.html -->

<h2 class="title">
    <a href="{% url 'post_detail' pk=post.pk %}">{{ post.title }}</a>
</h2>

设定 Read More 按钮的连结

在 home.html 中找到以下内容:

<!-- home.html -->

<a class="read-more" href="#">
    Read More <i class="fa fa-arrow-right"></i>
</a>

修改如下:

<!-- home.html -->

<a class="read-more" href="{% url 'post_detail' pk=post.pk %}">
    Read More <i class="fa fa-arrow-right"></i>
</a>

验收成果

连至 http://127.0.0.1:8000/ 。现在只要点击各个日记的标题或 Read More 按钮,就会显示那该篇日记的详细页面。

Django Girls Trips - Post page

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文