---
# System prepended metadata

title: 'Django 2.0 文章集 [6] 進階特性完善 blog app'
tags: [python, Django, django2.0]

---

#  Django 2.0 文章集 [6] 進階特性完善 blog app

###### tags: `Django`, `django2.0`, `python`

##  § 電子郵件分享貼文

- [ ]   (1) [管理員 email] 到 mysite/settings.py 設定 SMTP
- [ ]   (2) [管理員 email] 到以下網址 (Google) 設定允許低安全性應用程式
      設定完後方可用該 email 寄信
  http://myaccount.google.com/lesssecureapps
- [ ]   (3) 開啟 django shell，測試是否能正常送信
> from django.core.mail import send_mail

> send_mail('Subject here', 'Here is the message.',\
    	      'from@example.com', 
              ['to@example.com'],\
              fail_silently=False)
Example:
send_mail("一封限時批", "直面詛咒，心亦雀躍。",\
          "sender_account@gmail.com",\
          ["receiver_account@gmail.com"],\
          fail_silently=False)

- [ ] (4) 編輯 views.py
####  加上避免 CSRF 攻擊的 token: {{ csrf_token }}
  詳參: https://owasp.org/www-community/attacks/csrf

##  § 添加標籤功能

pip install django-taggit==0.22.2

###  編輯 mysite/mysite/settings.py
  INSTALLED_APPS 添加以下項目:
  INSTALLED_APPS = [
      ... 
      "taggit",
  ]

###  編輯 mysite/blog/models.py
```
  class Post(models.Model):
      ...
      tags = TaggableManager()
```

>python manage.py makemigrations blog
> python manage.py migrate

###  用 shell 測試看看
> from blog.models import Post

###  為某篇文章加上標籤並印出測試
> post = Post.objects.get(id=1)
> post.tags.add("tutorial", "django")
> post.tags.all()
  執行結果: 
 <QuerySet [<Tag: django>, <Tag: tutorial>]>

###  移除標籤並印出測試
> post.tags.remove("tutorial")
> post.tags.all()
  執行結果: 
 <QuerySet [<Tag: django>]>

## 將視圖加入標籤功能
  編輯 views.py
```
from taggit.models import Tag

def post_list(request, tag_slug=None):
    tag_ = None
    if tag_slug is not None:
        tag_ = get_object_or_404(Tag, slug=tag_slug)
        object_list = object_list.filter(tags__in=[tag_])
    return render(... ,
                  { ...
                   "tag": tag_})
```

##  編輯 mysite/blog/urls.py
  將下列(之前設定的) URL 路徑取消註解
  並加上一行新路徑(用於標籤)，如下:
```
urlpatterns = [
    path("", views.post_list, name="post_list"),
    ...
    path("tag/<slug:tag_slug>/", views.post_list,
         name="post_list_by_tag"),
]
```
  P.S. 由於剛剛編輯過了 post_list 視圖
       多傳了一個 tag 參數給模板 (且相關 URL 路徑也設定完畢)
       此處需要「編輯模板」來顯示 tag 的相關資訊
  編輯 mysite/blog/templates/blog/post/list.html

##  調整分頁機制以使用 all_posts
` {% include "pagination.html" with page=all_posts %}`
 
##  在 {% for %} 中加入印出標籤的程式碼如下:
  ```
{% for post in all_posts %}
    {% if tag %}
       <h2>有關 '{{ tag.name }}' 的所有貼文:</h2>
    {% endif %}
    ...
    ...
    <p class="tags">
      文章分類:
      {% for tag in post.tags.all %}
        <a href='{% url "blog:post_list_by_tag" tag.slug %}'>
          {{ tag.name }}
        </a>
        {% if not forloop.last %}, {% endif %}
      {% endfor %}
    </p>
    ...
    ...
  {% endfor %}
```

  做完上述 models, views, urls, templates 的修改
  啟動 server 後應可看到列表頁的各文章都帶有"文章分類"
  (若後台有添加文章分類)，且點擊某一標籤，會導引到
  一個「皆含有該分類的文章」的頁面。
