Djangoで、SNS共有リンクを作る

Twitterでシェア FaceBookでシェア はてなブックマークでシェア

Python - Django
2018年12月3日9:11に更新(約10日前)
2018年12月3日6:27に作成(約10日前)

概要

Djangoで、Twitter, Facebook, はてなブックマークの共有リンクを作っていきます。

以下のような感じです。 共有リンクが表示される

「記事の一覧」の下にあるのはウェブサイトのトップページ共有リンクで、このブログでいうとhttps://narito.ninja/の共有リンクです。

四角の中にあるのは記事の共有リンクで、このブログでいうとhttps://narito.ninja/detail/1/ とかhttps://narito.ninja/detail/2/ といった個別ページの共有リンクです。一覧画面にも貼りつつ、記事詳細ページにも同様のものが貼ってあったりしますね。

TwitterやFacebook各サービスに共有リンク・ボタンを作成するための機能があったりするのですが、表示されるまで遅かったりして疲れるので、単純なa要素として作成します。

できあがるa要素

先に、どういうa要素を作ればいいのかを紹介します。

静的なHTMLを作っている場合は、これをコピペしてURL部分(Twitterはテキストも)を変えるだけで済みます。

twitter

<a href="https://twitter.com/share?url=http://127.0.0.1:8000/detail/1/&text=L4D2をやりました ホームページ名" target="_blank" rel="nofollow">
    Twitterでシェア
</a>

Facebook

<a href="https://www.facebook.com/sharer/sharer.php?u=http://127.0.0.1:8000/detail/1/" target="_blank" rel="nofollow">
    Facebookでシェア
</a>

はてなブックマーク

<a href="http://b.hatena.ne.jp/entry/http://127.0.0.1:8000/detail/1/" target="_blank" rel="nofollow">
    はてなブックマークでシェア
</a>

URLの作成

上のa要素内のhref属性部分をDjangoで動的に作る必要があります。完全なURLでないといけないので、単に{% url app:top %}のように書くだけではいけません。スキームとホストの取得も必要です。

スキーム

スキーム...httphttps部分のことです。

{{ request.scheme }}

テンプレートにはrequestオブジェクトが自動的に渡されるので、ビューから渡さなくてもテンプレートでは無条件で{{ request }}と使えます。{{ user }}なんかもそうですね。

ホスト

ざっくり言うとドメインと大体同じ部分のことです。narito.ninjaですね。

{{ request.get_host }}

get_host()は、実はリクエストオブジェクトのメソッドなのですが、テンプレートでは呼び出し可能オブジェクトは自動的に呼び出してくれます。

パス

/とか/detail/1/の部分です。これはおなじみのurlタグでできますね。

{% url 'app:post_detail' post.pk %}

完全なURLの作成

上の3つを組み合わせて、以下のようにすると完全なURLが作成できます。

{{ request.scheme }}://{{ request.get_host }}{% url 'app:post_detail' post.pk %}

ビューで作成する場合

ビューでURL文字列を作成する必要がある場合、よく以下のようにします。

from django.contrib.sites.shortcuts import get_current_site
from django.shortcuts import resolve_url
...
...
    current_site = get_current_site(request)
    domain = current_site.domain
    url = '{0}://{1}{2}'.format(
        request.scheme,
        domain,
        resolve_url('app:hogehoge'),
    )

テンプレートの例と違うのは、ドメインの取得をget_current_site(request).domainとしていることです。

サイトフレームワークを使っているとドメインを自分で設定することもあります。そういった場合、get_current_site(request).domainはその自分で設定したドメインを取得してくれますし、サイトフレームワークを使っていなければ内部的にrequest,get_host()を呼び出します。

ただ、そこまでしなくても大抵はrequest.get_host()で事足ります。なので、今回テンプレートでそのようにしています。面倒ですし。

ソースコード

概要でお見せしたもののソースコードも貼っておきます。

models.py

from django.db import models


class Post(models.Model):
    title = models.CharField('タイトル', max_length=255)

urls.py

from django.urls import path
from . import views

app_name = 'app'

urlpatterns = [
    path('', views.PostList.as_view(), name='post_list'),
    path('detail/<int:pk>/', views.PostDetail.as_view(), name='post_detail'),
]

views.py

from django.views import generic
from .models import Post


class PostList(generic.ListView):
    model = Post


class PostDetail(generic.DetailView):
    model = Post

base.htmlはBootstrap4のスターターテンプレートです。後でBootstrap4のボタン例も紹介するので使っているだけです。

<!doctype html>
<html lang="ja">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">

    <title>サンプル</title>
  </head>
  <body>
    <div class="container mt-5">
        {% block content %}{% endblock %}
    </div>

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
  </body>
</html>

post_list.htmlですが、SNSリンクはよく使うので別テンプレートに分けました。

{% extends 'app/base.html' %}

{% block content %}
    <h1>記事の一覧</h1>
    {% include 'app/includes/sns_button_for_top.html' %}
    <hr>

    {% for post in post_list %}
        <div style="border:5px double #4169e1;">
            <h2>{{ post.title }}</h2>
            {% include 'app/includes/sns_button_for_detail.html' %}
        </div>
        <br>
    {% endfor %}
{% endblock %}

includesといったディレクトリに入れておくことで、includeされるテンプレートであることが分かりやすいのでお勧めです。

sns_button_for_topはトップページ用の共有リンクです。概要の画像で言う一番上のですね。

<a href="https://twitter.com/share?url={{ request.scheme }}://{{ request.get_host }}{% url 'app:post_list' %}&text=記事一覧 - ホームページ名" target="_blank" rel="nofollow">
    Twitterでシェア
</a>

<a href="https://www.facebook.com/sharer/sharer.php?u={{ request.scheme }}://{{ request.get_host }}{% url 'app:post_list' %}" target="_blank" rel="nofollow">
FaceBookでシェア
</a>

<a href="http://b.hatena.ne.jp/entry/{{ request.scheme }}://{{ request.get_host }}{% url 'app:post_list' %}" target="_blank" rel="nofollow">
    はてなブックマークでシェア
</a>

今回{% url 'app:post_list' %}がトップページに当たります。

sns_button_for_detailは、記事用の共有リンクですね。

<a href="https://twitter.com/share?url={{ request.scheme }}://{{ request.get_host }}{% url 'app:post_detail' post.pk %}&text={{ post.title }} - ホームページ名" target="_blank" rel="nofollow">
    Twitterでシェア
</a>

<a href="https://www.facebook.com/sharer/sharer.php?u={{ request.scheme }}://{{ request.get_host }}{% url 'app:post_detail' post.pk %}" target="_blank" rel="nofollow">
Facebookでシェア
</a>

<a href="http://b.hatena.ne.jp/entry/{{ request.scheme }}://{{ request.get_host }}{% url 'app:post_detail' post.pk %}" target="_blank" rel="nofollow">
    はてなブックマークでシェア
</a>

Bootstrap4を使う例

Bootstrap4を使うと、簡単に見た目に良いものが作れます。

<div class="row">
    <div class="col-sm-4">
        <a class="btn btn-outline-primary btn-block" href="https://twitter.com/share?url={{ request.scheme }}://{{ request.get_host }}{% url 'app:post_list' %}&text=記事一覧 - ホームページ名" target="_blank" rel="nofollow">
            Twitterでシェア
        </a>
    </div>
    <div class="col-sm-4">
        <a class="btn btn-outline-primary btn-block" href="https://www.facebook.com/sharer/sharer.php?u={{ request.scheme }}://{{ request.get_host }}{% url 'app:post_list' %}" target="_blank" rel="nofollow">
        FaceBookでシェア
        </a>
    </div>
    <div class="col-sm-4">
        <a class="btn btn-outline-primary btn-block" href="http://b.hatena.ne.jp/entry/{{ request.scheme }}://{{ request.get_host }}{% url 'app:post_list' %}" target="_blank" rel="nofollow">
            はてなブックマークでシェア
        </a>
    </div>
</div>

よく見かけるやつですね。
よく見かけるSNSボタン

スマホサイズでも良い感じです。
スマホ対応SNSボタン

余白部分が気になるのなら、<div class="row no-gutters">としましょう。
余白のないSNSボタン

Twitterでシェア FaceBookでシェア はてなブックマークでシェア

記事にコメントする