Djangoで動的サブドメインの実装方法|サンプルコードを紹介

Djangoで動的サブドメインの実装方法|サンプルコードを紹介 プログラミング
Djangoで動的サブドメインの実装方法|サンプルコードを紹介
スポンサーリンク

こんにちは、こがたです。

この記事ではPythonのWebフレームワーク「Django」を使用した動的サブドメインの実装方法を紹介します。

対象読者
  • Djangoで動的サブドメインを実装したい
  • サブドメインって?
  • データごとにドメインを変えたい
  • Djangoの基本を理解している

まずサブドメインを利用するメリット、デメリットを説明します。

次にMac環境でのドメイン設定方法を紹介します。
一般的な「/etc/hosts」では動的なサブドメインを使用することができません。

コンテンツごとにサブドメインを変更するサンプルコードを紹介します。
※Djangoの基本は理解している上での説明となります。

サブドメインの利用用途

サブドメイン

サブドメインを利用することで、ドメイン(独自ドメイン)を分割してりようすることができます。

サブドメインを利用するメリット
  • SEOで他のサブドメインサイトから影響を受けない
  • ジャンルごとにサイトに分割でき、ブランドに統一感がでる
  • 1つのサーバで運用できる

大きいサイトを開発する場合、利用するケースが多いでしょう。

こがた
こがた

Yahooのサイトは「news」「shopping」など多くのサブドメインを利用しています

サブドメインを利用するデメリット
  • 各サイト(サブドメインごと)のSEOが上がりにくい
  • SSL証明書など、設定が必要

サブドメインを利用することで、各サブドメインごとのサイトのコンテンツ量が増えづらく、SEOに評価されるまで、時間がかかります。

また、SSL証明書について、ワイルドカードを使用するなど設定が必要になります。

ローカルでドメイン準備(Mac環境)

ローカルでドメイン準備(Mac環境)

ローカルで開発しているときに、よく利用されるIPアドレス(URLの実態)は「127.0.0.1」であることが多いです。

開発を進めるにあたり、このIPアドレスを「□□□.○○○.com」などのように名前を割りあてる必要があります。

一般的に名前を割り当てる場合に利用されるのが「/etc/hosts」ファイルですが、1つずつ設定することしかできません。

# サンプル
127.0.0.1 www.example.com
127.0.0.1 test.example.com
127.0.0.1 ex.example.com

これだと動的、状況によって違うサブドメインは利用できないよぉ〜

そこで利用するのが『Dnsmasq』です。
サブドメインにワイルドカードを使用することができ、動的なサブドメインにも対応できるようになります。

MacでのDnsmasq利用方法

まずは「dnsmasq」をbrewを利用してインストールします。

brew install dnsmasq

インストールすることで作成された「/usr/local/etc/dnsmasq.conf」に以下を追加してください。

address=/.example.com/::1
address=/.example.com/127.0.0.1

ここでは「example.com」というドメインを使用していますが、利用するドメインに変更してください。
「.」を入れることでワイルドカードを設定しています。

つぎにDnsmasqにローカルの名前解決させていきます。
以下を実行してドメインごとのファイルを作成します。

vim /etc/resolver/example.com

ーーーーー 内容 ーーーーー
nameserver ::1
nameserver 127.0.0.1

ファイル名はドメイン名としてください。

こがた
こがた

これで動的なサブドメインを利用する環境が整いました!

Djangoで動的サブドメインを実装していきましょ〜

Djangoでの動的サブドメイン実装

この記事ではContentというモデルを作成し、それぞれのサブドメインを動的に生成します。

実装する動的サブドメイン例
  • http://content1.example.com → content1のコンテンツが表示
  • http://content2.example.com → content2のコンテンツが表示
イメージ動画
こがた
こがた

↑のようにモデルごとにサブドメインを変えることができるようになります

サブドメインを利用するために「djano-hosts」モジュールを使用します。

以下のコマンドを実行してインストールしてください。

pip install django-hosts

プロジェクトの設定

この記事では「domain_project」というプロジェクト名にしています。

domain_project/settings.py」を以下のように変更してください。

ALLOWED_HOSTS = ['.example.com']

〜〜〜

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django_hosts',    # ←追加する 
]

〜〜〜

MIDDLEWARE = [
    'django_hosts.middleware.HostsRequestMiddleware',    # ←一番上に追加する
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django_hosts.middleware.HostsResponseMiddleware',    # ←一番下に追加する
]

〜〜〜

ROOT_URLCONF = 'domain_project.urls'
PARENT_HOST = 'example.com:8000' # ←追加(本来はポートなしで設定する)
ROOT_HOSTCONF = 'domain_project.hosts' # ←追加(hosts設定は後ほど):プロジェクト名は変更してください
DEFAULT_HOST = 'www' # ←追加(デフォルトとなるサブドメイン)

「ALLOWED_HOSTS」でアクセスを認めるドメインを設定しています。
「.」でワイルドカード設定とし、動的なサブドメインにも対応できるようになります。
※マッチしないものはエラーがはきだされます

「PARENT_HOST」はテンプレートからドメインを取得するときに使用します。

「ROOT_HOSTCONF」は後ほど作成する「domain_project/hosts.py」ファイルを指しています。

「DEFAULT_HOST」はデフォルトとなるサブドメインを設定します。
この記事では「www.example.com」がメインのドメインとなります。

hostsファイルの設定

「ROOT_HOSTCONF」で設定した「domain_project/hosts.py」を以下の内容で作成します。

from django.conf import settings
from django_hosts import patterns, host

host_patterns = patterns(
    '',
    host(r'www', settings.ROOT_URLCONF, name='www'),
    host(r'([0-9a-zA-Z\-\_]+)', 'contents.domain_urls', name='domain_contents'),
)

基本的に考え方はDjangoのurlsファイルと同様です。

host()引数の説明
  • 1つ目:マッチするサブドメイン
  • 2つ目:読み込むurlsファル
  • 3つ目:サブドメインの名前(テンプレートなどで使用)

デフォルトのサブドメイン「www」が呼ばれたら、「ROOT_URLCONF」でurlを読み込みます。

それ以外の正規表現「([0-9a-zA-Z-_]+)」にマッチしたサブドメインが呼ばれた場合は、「contents.domain_urls」を読み込むようにしています。

こがた
こがた

サブドメインでどのURLファイルを読むのか判断して、ディレクトリからどのViewを読むのか判断する流れになります!

urlsファイルの設定

ここでは以下のurlsファイルを用意します。

urlsファイル
  • www→contents/urls.py
  • コンテンツごとのサブドメイン→contents/domain_urls.py

contentsというアプリを作成しています。
※アプリの詳細はこの記事では省略します

from django.urls import path

from . import views

app_name = 'contents'

urlpatterns = [
    path('', views.ContentList.as_view(), name='content_list'),
]

サブドメインが「www」だった場合に読まれるurlsファイルです。
ここでは一覧画面を表示するViewにしています。

from django.urls import path

from . import views

app_name = 'domain_contents'

urlpatterns = [
    path('', views.ContentDetail.as_view(), name='content_detail'),
]

サブドメインが「www」以外でhostsファイルに設定した正規表現にマッチしたら読み込まれます。

ここは詳細画面を表示するViewを呼び出すようにしています。

viewsの実装

この記事では汎用ビューを使用して、templatesを読むようにしています。

from django.shortcuts import render
from django.views import generic

from .models import Content
from .utilities import get_content_by_domain
 
 
class ContentList(generic.ListView):
    model = Content


class ContentDetail(generic.TemplateView):
    model = Content
    template_name = 'contents/detail.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        context['content'] = get_content_by_domain(self.request)


        return context

独自で作成した「utilities.py」というファイルを利用しています。

from django.shortcuts import get_object_or_404

from .models import Content

# ドメイン取得
def get_hostname(request):
    return request.get_host().split(':')[0].lower()

# サブドメイン取得
def get_subdomain(request):
    hostname = get_hostname(request) 
    return hostname.split('.')[0]

# サブドメインからコンテンツ取得
def get_content_by_domain(request):
    domain = get_subdomain(request)
    content = get_object_or_404(Content, domain=domain)
    return content 

contentsモデルにdomainというフィールドを持たせておき、サブドメインがマッチするかでインスタンスを取得するようにしています。

templates(html)でのリンク

ここでは各contentの詳細画面にリンクする一覧画面のtemplatesを説明します。

{% extends "contents/base.html" %}
{% load hosts %}
{% block content %}
<div>
    <div>
        <p>タイトル</p>
    </div>

    {% for content in object_list %}
    <div>
        <p>**************</p>
        <p>コンテンツ名:{{ content.name }}</p>
        <p>設定したドメイン:{{ content.domain }}</p>
        <p>
            <a href="{% host_url 'content_detail' host 'domain_contents' content.domain %}">詳細ページ</a>
        </p>
        <br>
        <br>
    </div>
    {% endfor %}
</div>
{% endblock %}
 

「{% load hosts %}」を記載することでリンク先にhostsの設定もできるようになります。

リンクの設定「{% host_url ‘content_detail’ host ‘domain_contents’ content.domain %}」を説明します。

リンクの内容
  • host_url:urlsファイルで設定したname属性を指定
  • host :hostsファイルで設定したname属性を指定

「host_url」の部分は従来の「url ‘〇〇’」と同じ書き方です。

「host_url」と「host」の間に変数をいれると、動的なURLディレクトリを指定できます。

{% host_url 'content_detail' content.id host 'domain_contents' content.domain %}

「host」の間に変数をいれると、リンク先のサブドメインを指定できます。

こがた
こがた

この内容を元にviewsやtemplatesを修正していけば、Djangoのサブドメインは自由に利用できるようになります。

カスタマイズしてご利用ください。

【学習方法】初心者・中級者

Djangoは一度仕組みを理解すれば、簡単に複雑なWebアプリを構築することができます。

Python初心者の方は『PyQ』で学習することをオススメします。

PyQはPythonに特化した学習スクールで、Pythonができること、すべて網羅しているスクールになります。

スクールで学べること
  • Python文法:基礎から実務レベルまで
  • 設計方法:実務向き
  • ライブラリー利用
  • Web開発
  • API開発
  • スクレイピング
  • データ分析と必要な数学
  • 機械学習
  • 統計

「プログラムとは?」というところから教えてくれるので、初心者はもっとも効率的にPythonを学ぶことができます。
逆に中級者以上の方は物足りなく感じることが多いと思います。

中級者以上の方は『Udemy』で講座を購入して学習する方法がオススメです。
10万以上の講座があり簡単な内容から応用的な内容まで選ぶことができます。

セール中は1万円以上する講座が1,000円代で購入できるので、セールを狙ってみてください!

Udemyはいつでも、どこでも、何回でも受講できますが、モチベーションを保たないと、やり遂げることができないのが注意点です。

自分にあった学習方法でPythonをマスターしていきましょう!

最後まで読んでくださり、ありがとうございました!!!

コメント

タイトルとURLをコピーしました