ローカルで作成した Django アプリケーションを Ubuntu の本番環境へ反映する

Mac のローカル環境で作成した Django プロジェクトをさくらの VPS で用意した Ubuntu 環境へ反映する際の流れをメモしています。

下記が完了していることを想定しています。

  • Web サーバーの設定が完了済み(筆者は Nginx を使用)
  • 仮想環境を作るディレクトリが決めてある
  1. データベースを本番環境にコピーする
    • ローカル環境での作業
    • 本番環境での作業
  2. ローカル環境のパッケージを本番環境で再現
    • requirements.txt の作成
    • requirements.txt を本番環境へコピー
    • 本番環境で Python 仮想環境を作成
    • requirements.txt によるパッケージインストール
  3. gunicorn のインストール
  4. settings.py の編集
    • ファイルを分割する必要性
    • 開発環境の runserver 実行時に settings_dev.py を指定
    • settings.py(本番環境用)の編集
  5. Django ソースコードを本番環境に配置
    • 本番環境への git のインストール
    • リモートリポジトリから本番環境へファイルをコピー
  6. データベースのログイン情報をサーバーの環境変数に記述
  7. 静的ファイルの配置

1. データベースを本番環境にコピーする

検証環境で準備したデータベース、テーブル、そしてデータを本番環境でも反映します。

ここはうまくやれば一行スクリプト書いて終了する方法もある様ですが、色々とエラーが出て逆にめんどくさそうだったのでステップバイステップでやっていきます。

ローカル環境での作業

まずローカル環境でコマンド「mysqldump データベース名 > dump.txt」を実行し、dump ファイルを作成します。

% mysqldump graffuhs > dump.txt                                                              
%

それを FTP か何かで本番環境へアップロードします。

本番環境での作業

本番環境に接続し、本番環境の MySQL でデータベースを作成します。

mysql> create database データベース名;

そしてコマンド「sudo mysql データベース名 < dump.txt」を実行します。

$ sudo mysql データベース名 < dump.txt
$

これで本番環境の MySQL にもローカル環境と同じデータベース、テーブル、そしてデータがコピーされました。

2. ローカル環境のパッケージを本番環境で再現

ローカル環境の Python 関連パッケージを本番環境でも再現するため、ローカル環境で requirements.txt ファイルを作成し、それを元に本番環境でパッケージインストールをさせます。

requirements.txt の作成

ローカル環境の Python 仮想環境へ移り、コマンド「pip freeze > requirements.txt」を実行します。

% pip freeze > requirements.txt

requirements.txt を本番環境へコピー

コマンド「scp requirements.txt 本番環境のユーザー名@本番環境のホスト名(もしくは IP アドレス):保存先のディレクトリ」を実行します。

だいぶ長いですが下記の例だとすると。。。

  • 本番環境のユーザー名: vpsadmin
  • 本番環境のホスト名: xx1-234-56789.vs.sakura.ne.jp
  • 保存先のディレクトリ: /var/www/example.com/html

下記の様になります。

scp requirements.txt vpsadmin@xx1-234-56789.vs.sakura.ne.jp:/var/www/example.com/html

無事本番環境に requirements.txt がコピーされました。

$ ls
pythonvenv  requirements.txt

本番環境で Python 仮想環境を作成

本番環境のディレクトリへ移動し、Python の仮想環境を作成します。

$ python3.9 -m venv pythonvenv
$ ls
pythonvenv

requirements.txt によるパッケージインストール

本番環境の Python 仮想環境に入った状態で、コマンド「pip install -r requirements.txt」を実行します。

(pythonvenv) $ pip install -r requirements.txt

すると requirements.txt の内容を元に Django を含めローカル環境で使っていたものと同じパッケージがインストールされます。

3. gunicorn のインストール

本番環境でのみ必要となるものとして、アプリケーションサーバーがあります。今回は gunicorn を使います。

Python 仮想環境内でアプリケーションサーバーの gunicorn をインストールします。

(pythonvenv) $ pip install gunicorn

4. settings.py の編集

ファイルを分割する必要性

settings.py は本番環境と開発環境で内容が異なる部分が出てくるので、下記の様にファイルを分ける必要があります。(ファイル名は任意)

  • settings_common.py:開発環境と本番環境で共通の部分を記述
  • settings.py:本番環境でのみ適用する部分を記述
  • settings_dev.py:開発環境でのみ適用する部分を記述

settings.py と settings_dev.py それぞれに「from .settings_common import *」と記述し、共通部分を settings_common.py から読み込む様設定します。

開発環境の runserver 実行時に settings_dev.py を指定

runserver 実行時、デフォルトでは settings.py が設定ファイルとして読み込まれますが、今後開発環境(ローカル環境)では settings_dev.py を使う必要があります。

そのため、今後開発環境で runserver を実行する際は settings_dev.py を「runserver --settings=プロジェクトディレクトリ名.settings_dev」の形式で渡して実行します。

(inmybag) % python manage.py runserver --settings=some_project.settings_dev

settings.py(本番環境用)の編集

DEBUG の変更

False に変更

DEBUG = False

ALLOWED_HOSTS の変更

ドメイン名を設定。

ALLOWED_HOSTS = ['example.com']

Web サーバーで www.example.com から example.com のリダイレクトを行っていれば example.com のみを設定するだけで大丈夫。

静的ファイルの本番環境での配置場所

STATIC_ROOT = '/var/www/examlpe.com/html/static'

5. Django ソースコードを本番環境に配置

本番環境への git のインストール

本番環境でコマンド「sudo apt update」を実行しパッケージリストを更新、その後「sudo apt install git」で git をインストールします。

$ sudo apt update
$ sudo apt install git
Reading package lists... Done
Building dependency tree       
Reading state information... Done
git is already the newest version (1:2.25.1-1ubuntu3.1).
git set to manually installed.
0 upgraded, 0 newly installed, 0 to remove and 18 not upgraded.

リモートリポジトリから本番環境へファイルをコピー

プロジェクトフォルダをリポジトリに設定しているので、プロジェクトフォルダを配置したい場所へ移動した上で git clone を実行します。

$ git clone https://github.com/ユーザー名/リポジトリ名.git

これで本番環境にもプロジェクトフォルダがコピーされました。

今後作業する際は何かにつけて「pkill gunicorn」で gunicorn を終わらせた方が良いです。エラーが起きた時にいくらコードを修正しても治らないまま数時間経って、「pkill gunicorn」一発で治ったこともありました。

6. データベースのログイン情報をサーバーの環境変数に記述

MySQL のデータベースを使用していて、settings.py ではユーザー名とパスワードを環境変数から取る様に設定しています。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'データベース名',
        'USER': os.environ.get('DB_USER'),
        'PASSWORD': os.environ.get('DB_PASSWORD'),
        'HOST': '',
        'PORT': '',
    }
}

そのため、サーバーの環境変数として記述します。ホームディレクトリの .bashrc ファイルの最下部に下記を追加しました。

export DB_USER='ユーザー名'
export DB_PASSWORD='パスワード'

7. 静的ファイルの配置

コマンド「python manage.py collectstatic」を実行し、settings.py で STATIC_ROOT に設定したパスに静的ファイルを集約します。

$ python manage.py collectstatic

これでとりあえず本番環境でも動くと思います。

Django の クラスベースビューで URL のパラメータを使う

まず URL ディレクトリの文字列を使う場合の復習

Django の ListView などでテンプレートに返すデータをフィルタリングする際、urls.py で設定した URL ディレクトリの文字列を取得してそれを元にすることがあると思います。

下記の様な感じで get_queryset 関数で self.kwargs から値を取り出す感じですね。

# urls.py
urlpatterns = [
    path('<str:some_code>/', views.SomeData.as_view(), name="some_data"),
]
# views.py
class SomeData(generic.ListView):
    ### 一部省略 ###
    def get_queryset(self):
        code = self.kwargs['some_code']
        return SomeDataModel.objects.filter(some_code_column=code)

ただ、今回はそうではなく URL のパラメータを「ドメイン名.com/?キー=値&キー=値」の形式で取得してそれをデータ取得に使いたいと思います。

URL のパラメータを使いたい

self.request.GET.get(パラメータキー) で取得

get_queryset 関数をオーバーライドする際に self.request.GET.get(パラメータのキー) で取得できます。

例えば「http://127.0.0.1:8000/devicelist/?brand_nm=apple&category=laptop,phone」の様な URL の場合。

「?brand_nm=apple&category=laptop,phone」の部分をビューの処理に使いたいとします。

# views.py 内 get_queryset 関数
def get_queryset(self):
    brand = self.request.GET.get('brand_nm')
    return SomeDataModel.objects.filter(brand_nm=brand)

値が一つだけの場合

値が一つだけの場合(brand_nm=apple)は「self.request.GET.get(キー)」でそのまま値が一つ取得できます。

print(self.request.GET.get('brand_nm'))
# apple

値が複数の場合

複数の値を「,」で繋げて URL に渡した場合(category=laptop,phone)は、「,」が含まれただけの一つの文字列になっています。

print(self.request.GET.get('category'))
# laptop, phone

なので一旦 .split(',') を通してリストにしてあげる必要があります。

print(self.request.GET.get('category').split(','))
# ['laptop', 'phone']
print(self.request.GET.get('category').split(',')[0])
# laptop
print(self.request.GET.get('category').split(',')[1])
# phone

値を指定していない場合

URL で渡していないキーを指定すると None が返ってきます。

print(self.request.GET.get('product_type'))
# None

Django の ModelForm で select option をテーブルから参照する

やりたいこと:Django の ModelForm を作るときに、ドロップダウンメニューの選択肢(select option)をデータベースのテーブルから持ってきたい。

結論から言いますと Foreign Key を使って別のテーブルのユニークキーをフォームの選択肢として利用します。

models.py でドロップダウンにしたいカラムに models.ForeignKey を適用

まず、models.py でドロップダウン表示にしたい項目に models.ForeignKey を適用します。

別テーブルでユニークになっている値(つまりドロップダウンの候補になる値)が入るという設定をします。

# models.py

class IgMstProduct(models.Model):
    id = models.AutoField(primary_key=True)
    product_nm = models.CharField(max_length=60, blank=True, null=True)
    brand_cd = models.ForeignKey('IgMstBrand',on_delete=models.SET_NULL, null=True, db_column='brand_cd')
    product_url = models.TextField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'ig_mst_product'

上記の設定時、「db_column」で DB 側で実際に情報を受け取るカラム名を指定しないと、フォーム Submit 時に「1054, "Unknown column '〜_id' in 'field list'"」というエラーが返ってくると思います。

詳しくは調べていませんがどうやら Django が自動的に「〜_id」のカラム名で処理をしようとするらしいです。

forms.py で ModelChoiceField を設定

下記の様に対象の項目に対して forms.ModelChoiceField(queryset=モデル名.objects.all()) を設定してみると、なんとなくそれっぽくドロップダウンが表示されます。

# forms.py

class IgProductForm(forms.ModelForm):
    brand_cd = forms.ModelChoiceField(queryset=IgMstBrand.objects.all())

    class Meta:
        model = IgMstProduct
        fields = ('product_nm', 'product_category', 'brand_cd', 'product_url',)

が、このままだとドロップダウンの表示名が下記の様に「モデル名 object (1)」とかになるので変更します。

<select name="brand_cd" required id="id_brand_cd">
  <option value="" selected>---------</option>
  <option value="1">モデル名 object (1)</option>
  <option value="2">モデル名 object (2)</option>
  <option value="3">モデル名 object (3)</option>
  <option value="4">モデル名 object (4)</option>
  <option value="5">モデル名 object (5)</option>
  <option value="6">モデル名 object (6)</option>
</select>

ModelChoiceField を継承する別クラスを作成し、そこで label_from_instance 関数をオーバーライドし、return obj.表示したいカラム名 とすれば表示したいカラム名が表示名が変わります。

# forms.py

class CustomModelChoiceField(forms.ModelChoiceField):
    def label_from_instance(self, obj): # label_from_instance 関数をオーバーライド
         return obj.brand_nm # 表示したいカラム名を return


class IgProductForm(forms.ModelForm):
    brand_cd = CustomModelChoiceField(queryset=IgMstBrand.objects.all()) # 上記のクラスを参照する様変更

    class Meta:
        model = IgMstProduct
        fields = ('product_nm', 'product_category', 'brand_cd', 'product_url',)
<select name="brand_cd" required id="id_brand_cd">
  <option value="" selected>---------</option>
  <option value="1">Nikon</option>
  <option value="2">Canon</option>
  <option value="3">Sony</option>
  <option value="4">Fujifilm</option>
  <option value="5">Leica</option>
  <option value="6">Olympus</option>
</select>

Django の REST framework で JSON を返す API を作る方法

Python 仮想環境内に作ったプロジェクトに API 用の独自のアプリケーションを作り、その中に View を作ります。

ここで紹介するのは単純にテーブル内のデータを全て GET で抽出してそのまま JSON 形式で返すだけのものです。POST や DELETE などは触れていません。

  1. 下準備
    • API 用 Django アプリケーションの作成
    • djangorestframework のインストール
    • urls.py の設定
    • models.py にモデルを記述
  2. シリアライザの作成
  3. ビューの作成
    • class based view の場合
    • function based view の場合
  4. 動作確認

下準備

API 用 Django アプリケーションの作成

API 用にアプリケーション「api」を作成します。

% python manage.py startapp api

settings.py の INSTALLED_APPS に追加します。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'api.apps.ApiConfig', # 追記
]

djangorestframework のインストール

コマンド「pip install djangorestframework」を実行します。

% pip install djangorestframework
Collecting djangorestframework
  Downloading djangorestframework-3.12.4-py3-none-any.whl (957 kB)
     |████████████████████████████████| 957 kB 4.1 MB/s 
Requirement already satisfied: django>=2.2 in /Users/ユーザー名/PythonProjects/仮想環境名/lib/python3.8/site-packages (from djangorestframework) (3.2)
Requirement already satisfied: pytz in /Users/ユーザー名/PythonProjects/仮想環境名/lib/python3.8/site-packages (from django>=2.2->djangorestframework) (2021.1)
Requirement already satisfied: sqlparse>=0.2.2 in /Users/ユーザー名/PythonProjects/仮想環境名/lib/python3.8/site-packages (from django>=2.2->djangorestframework) (0.4.1)
Requirement already satisfied: asgiref<4,>=3.3.2 in /Users/ユーザー名/PythonProjects/仮想環境名/lib/python3.8/site-packages (from django>=2.2->djangorestframework) (3.3.4)
Installing collected packages: djangorestframework
Successfully installed djangorestframework-3.12.4
%

settings.py の INSTALLED_APPS に追加します。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'api.apps.ApiConfig',
    'rest_framework', # 追記
]

urls.py の設定

アプリケーション「api」ディレクトリに url.py を作成した上で、プロジェクトレベルの url.py から参照します。

from django.contrib import admin
from django.urls import path, include # 追記

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('api.urls')), # 追記
]

models.py にモデルを記述

API で使用したいモデルを models.py に記述します。

今回すでにデータベース上にテーブルを用意してあるのでコマンド「python manage.py inspectdb テーブル名」でモデル情報を抽出します。

% python manage.py inspectdb yt_analysis_07
# This is an auto-generated Django model module.
# You'll have to do the following manually to clean this up:
#   * Rearrange models' order
#   * Make sure each model has one field with primary_key=True
#   * Make sure each ForeignKey and OneToOneField has `on_delete` set to the desired behavior
#   * Remove `managed = False` lines if you wish to allow Django to create, modify, and delete the table
# Feel free to rename the models, but don't rename db_table values or field names.
from django.db import models


class YtAnalysis07(models.Model):
    channel_id = models.CharField(max_length=40, blank=True, null=True)
    channel_name = models.TextField(blank=True, null=True)
    view_count = models.BigIntegerField(blank=True, null=True)
    like_count = models.IntegerField(blank=True, null=True)
    dislike_count = models.IntegerField(blank=True, null=True)
    favorite_count = models.IntegerField(blank=True, null=True)
    comment_count = models.IntegerField(blank=True, null=True)
    video_count = models.IntegerField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'yt_analysis_07'
% 

クラス文を models.py にコピーしますが、その際に 1 つ「primary_key=True」のフィールドを持つ必要があるそうです。

シリアライザの作成

Python のリスト・辞書形式のデータを JSON に変換するためのシリアライザを作成します。

アプリケーションフォルダ(今回は api/ )に「serializers.py」というファイルを作成します。

from rest_framework import serializers
from .models import YtAnalysis07 # モデルをインポート

class APISerializer(serializers.ModelSerializer):
    class Meta:
        model = YtAnalysis07 # 使用するモデル
        fields = '__all__' # 処理対象にするフィールド(今回は全項目)

ビューの作成

API のビューを作成します。ざっくり言うとモデルからデータを抽出し、シリアライザに渡して JSON に変換し、その JSON データをレスポンスとして返します。

class based view の場合

from rest_framework import viewsets
from .serializers import APISerializer
from .models import YtAnalysis07

class DataListView(viewsets.ModelViewSet):
    queryset = YtAnalysis07.objects.all() # モデルからデータを抽出するクエリセット
    serializer_class = APISerializer # 使用するシリアライザ

urls.py の設定は下記の様にします。

from django.urls import path
from . import views

app_name = 'api'
urlpatterns = [
    path('data-list/', views.DataListView.as_view({'get': 'list'}), name="data-list"),
]

function based view の場合

from rest_framework.decorators import api_view
from rest_framework.response import Response
from .serializers import APISerializer
from .models import YtAnalysis07

@api_view(['GET']) # GET のみに対応
def dataList(request):
    api_data = YtAnalysis07.objects.all() # モデルからデータを抽出する
    serializer = APISerializer(api_data, many=True) # シリアライザにデータを渡す
    return Response(serializer.data) シリアル可されたデータを return で返す

urls.py の設定は下記の様にします。

from django.urls import path
from . import views

app_name = 'api'
urlpatterns = [
    path('data-list/', views.dataList, name="data-list"),
]

動作確認

設定した URL をブラウザに打ち込むと下記の様な画面が表示されます。JSON データも見えます。

ブラウザで URL を叩くと上記の様な画面で表示されますが、例えばターミナルで URL を requests.get すると下記の様に JSON 形式のデータだけが返ってきます。

>>> import requests
>>> r = requests.get('http://127.0.0.1:8000/api/data-list/')
>>> r.text
'[{"channel_id":"UCLkAepWjdylmXSltofFvsYQ","channel_name":"BANGTANTV","view_count":22423409,"like_count":7325674,"dislike_count":20936,"favorite_count":0,"comment_count":381315,"video_count":9},{"channel_id":"UCE_M8A5yxnLfW0KghEeajjw","channel_name":"Apple","view_count":19044060,"like_count":600159,"dislike_count":21023,"favorite_count":0,"comment_count":0,"video_count":10},

これを Django のテンプレートから JavaScript で呼び出すなどして活用します。

Mac「brew install mysqlclient」でエラー「pip install mysql で成功」

環境

OS: macOS Big Sur バージョン 11.2.2
Python: Python 3.8.3

brew install mysqlclient でエラー

Python 仮想環境で「brew install mysqlclient」を実行したら下記のエラーが発生しました。結論から言うと「pip install mysqlclient」の間違いだったことに後で気づきました。

が、それに気づく前に「pip install mysql」を実行して無事解決したので書いておきます。

エラーログ

==> Searching for similarly named formulae...
These similarly named formulae were found:
mysql-client                                                                                  mysql-client@5.7
To install one of them, run (for example):
  brew install mysql-client
Error: No available formula or cask with the name "mysqlclient".
==> Searching for a previously deleted formula (in the last month)...
Error: No previously deleted formula found.
==> Searching taps on GitHub...
Error: No formulae found in taps.

とりあえず一番初めのエラー「Error: No available formula or cask with the name "mysqlclient".」が気になる。

調べてみると、「pip install mysql」を実行してその後に「pip install mysqlclient」を実行するという書き込みを発見。

ただ実際は「pip install mysql」だけで成功しました。

pip install mysql で成功

仮想環境内でコマンド「pip install mysql」を実行。

(venv) % pip install mysql
Collecting mysql
  Downloading https://files.pythonhosted.org/packages/bf/5f/b574ac9f70811df0540e403309f349a8b9fa1a25d3653824c32e52cc1f28/mysql-0.0.2.tar.gz
Collecting mysqlclient (from mysql)
  Downloading https://files.pythonhosted.org/packages/3c/df/59cd2fa5e48d0804d213bdcb1acb4d08c403b61c7ff7ed4dd4a6a2deb3f7/mysqlclient-2.0.3.tar.gz (88kB)
     |████████████████████████████████| 92kB 5.7MB/s 
Installing collected packages: mysqlclient, mysql
  Running setup.py install for mysqlclient ... done
  Running setup.py install for mysql ... done
Successfully installed mysql-0.0.2 mysqlclient-2.0.3
WARNING: You are using pip version 19.2.3, however version 21.0.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
(venv) %

「pip install mysql」で mysqlclient もカバーされている?

ログをみるとちらほら「mysqlclient」について書かれているのが見えると思います。

そして「Successfully installed mysql-0.0.2 mysqlclient-2.0.3」の一文も。これってストレートに「mysql と mysqlclient が無事インストールされました。」ってことですよね?

% pip install mysqlclient

なので python を立ち上げて「import MySQLdb」を実行してみたら特にエラーも出ず。

「pip install mysqlclient」を実行しても何も変わらず

ここまで来てやっと「brew install 〜」ではなく「pip install 〜」を実行すべきだったと気づいて「pip install mysqlclient」を実行してみましたが、すでに完了しているとのことで何も変わりませんでした。

(venv) % pip install mysqlclient
Requirement already satisfied: mysqlclient in /Users/ユーザー名/PythonProjects/sample_venv/lib/python3.8/site-packages (2.0.3)
(venv) %

Python で YouTube Data API v3 を利用してチャンネル・動画情報を抽出する方法

  1. API キーの作成
  2. ライブラリのインストール
  3. API リクエストを試してみる
  4. 抽出できる情報

1. API キーの作成

「認証情報」のタブを開きます。

「+認証情報を作成」をクリックし「API キー」を選択。

黒く塗りつぶしてますが、ここに API キーが表示されます。

2. ライブラリのインストール

仮想環境内で Google APIs Client Library for Python をインストールします。

コマンド「pip install --upgrade google-api-python-client」を実行します。

(sample_venv) % pip install --upgrade google-api-python-client
Collecting google-api-python-client
  Downloading https://files.pythonhosted.org/packages/b7/56/bc7314cd180d1420e4ef11202dc9548ec22237a0a6de1aaf37b460ee7753/google_api_python_client-2.0.2-py2.py3-none-any.whl (6.5MB)
     |████████████████████████████████| 6.5MB 9.0MB/s 
Collecting google-auth<2dev,>=1.16.0 (from google-api-python-client)
  Downloading https://files.pythonhosted.org/packages/b5/ef/13d3b65c41ddde1a57e89de6adfc610093d109ebd472545a33e76dcdd8bf/google_auth-1.28.0-py2.py3-none-any.whl (136kB)
     |████████████████████████████████| 143kB 10.8MB/s 
Collecting google-api-core<2dev,>=1.21.0 (from google-api-python-client)
  Downloading https://files.pythonhosted.org/packages/66/21/891884b4fe2eda194e5cdc9ea617b63ab41e0aca595c865492380e2c10b3/google_api_core-1.26.2-py2.py3-none-any.whl (93kB)
     |████████████████████████████████| 102kB 11.4MB/s 
Collecting httplib2<1dev,>=0.15.0 (from google-api-python-client)
  Downloading https://files.pythonhosted.org/packages/15/7e/51e5bd333c0afa1c7bdbf98eb3b0ccf5167e2b1ecc8b4d13e9cc29291f81/httplib2-0.19.0-py3-none-any.whl (95kB)
     |████████████████████████████████| 102kB 11.4MB/s 
Collecting uritemplate<4dev,>=3.0.0 (from google-api-python-client)
  Using cached https://files.pythonhosted.org/packages/bf/0c/60d82c077998feb631608dca3cc1fe19ac074e772bf0c24cf409b977b815/uritemplate-3.0.1-py2.py3-none-any.whl
Collecting google-auth-httplib2>=0.0.3 (from google-api-python-client)
  Downloading https://files.pythonhosted.org/packages/ba/db/721e2f3f32339080153995d16e46edc3a7657251f167ddcb9327e632783b/google_auth_httplib2-0.1.0-py2.py3-none-any.whl
Requirement already satisfied, skipping upgrade: six<2dev,>=1.13.0 in /Users/ユーザー名/PythonProjects/sample_venv/lib/python3.8/site-packages (from google-api-python-client) (1.15.0)
Collecting cachetools<5.0,>=2.0.0 (from google-auth<2dev,>=1.16.0->google-api-python-client)
  Downloading https://files.pythonhosted.org/packages/bb/72/8df2e0dc991f1a1d2c6869404e7622e8ee50d80bff357dbb57c3df70305b/cachetools-4.2.1-py3-none-any.whl
Collecting pyasn1-modules>=0.2.1 (from google-auth<2dev,>=1.16.0->google-api-python-client)
  Using cached https://files.pythonhosted.org/packages/95/de/214830a981892a3e286c3794f41ae67a4495df1108c3da8a9f62159b9a9d/pyasn1_modules-0.2.8-py2.py3-none-any.whl
Collecting rsa<5,>=3.1.4; python_version >= "3.6" (from google-auth<2dev,>=1.16.0->google-api-python-client)
  Downloading https://files.pythonhosted.org/packages/e9/93/0c0f002031f18b53af7a6166103c02b9c0667be528944137cc954ec921b3/rsa-4.7.2-py3-none-any.whl
Requirement already satisfied, skipping upgrade: setuptools>=40.3.0 in /Users/ユーザー名/PythonProjects/sample_venv/lib/python3.8/site-packages (from google-auth<2dev,>=1.16.0->google-api-python-client) (41.2.0)
Collecting packaging>=14.3 (from google-api-core<2dev,>=1.21.0->google-api-python-client)
  Downloading https://files.pythonhosted.org/packages/3e/89/7ea760b4daa42653ece2380531c90f64788d979110a2ab51049d92f408af/packaging-20.9-py2.py3-none-any.whl (40kB)
     |████████████████████████████████| 40kB 8.7MB/s 
Requirement already satisfied, skipping upgrade: requests<3.0.0dev,>=2.18.0 in /Users/ユーザー名/PythonProjects/sample_venv/lib/python3.8/site-packages (from google-api-core<2dev,>=1.21.0->google-api-python-client) (2.25.1)
Collecting googleapis-common-protos<2.0dev,>=1.6.0 (from google-api-core<2dev,>=1.21.0->google-api-python-client)
  Downloading https://files.pythonhosted.org/packages/55/08/796a6bc0b550e2b7116041c953d3d5100016abea106131d71e5651826e7b/googleapis_common_protos-1.53.0-py2.py3-none-any.whl (198kB)
     |████████████████████████████████| 204kB 11.0MB/s 
Collecting protobuf>=3.12.0 (from google-api-core<2dev,>=1.21.0->google-api-python-client)
  Downloading https://files.pythonhosted.org/packages/62/be/f610958bf64f2a64b6b0b3403d17564af53bbfad5dad69f69b164cca038d/protobuf-3.15.6-cp38-cp38-macosx_10_9_x86_64.whl (1.0MB)
     |████████████████████████████████| 1.0MB 10.8MB/s 
Requirement already satisfied, skipping upgrade: pytz in /Users/ユーザー名/PythonProjects/sample_venv/lib/python3.8/site-packages (from google-api-core<2dev,>=1.21.0->google-api-python-client) (2021.1)
Requirement already satisfied, skipping upgrade: pyparsing<3,>=2.4.2 in /Users/ユーザー名/PythonProjects/sample_venv/lib/python3.8/site-packages (from httplib2<1dev,>=0.15.0->google-api-python-client) (2.4.7)
Collecting pyasn1<0.5.0,>=0.4.6 (from pyasn1-modules>=0.2.1->google-auth<2dev,>=1.16.0->google-api-python-client)
  Using cached https://files.pythonhosted.org/packages/62/1e/a94a8d635fa3ce4cfc7f506003548d0a2447ae76fd5ca53932970fe3053f/pyasn1-0.4.8-py2.py3-none-any.whl
Requirement already satisfied, skipping upgrade: certifi>=2017.4.17 in /Users/ユーザー名/PythonProjects/sample_venv/lib/python3.8/site-packages (from requests<3.0.0dev,>=2.18.0->google-api-core<2dev,>=1.21.0->google-api-python-client) (2020.12.5)
Requirement already satisfied, skipping upgrade: chardet<5,>=3.0.2 in /Users/ユーザー名/PythonProjects/sample_venv/lib/python3.8/site-packages (from requests<3.0.0dev,>=2.18.0->google-api-core<2dev,>=1.21.0->google-api-python-client) (4.0.0)
Requirement already satisfied, skipping upgrade: urllib3<1.27,>=1.21.1 in /Users/ユーザー名/PythonProjects/sample_venv/lib/python3.8/site-packages (from requests<3.0.0dev,>=2.18.0->google-api-core<2dev,>=1.21.0->google-api-python-client) (1.26.4)
Requirement already satisfied, skipping upgrade: idna<3,>=2.5 in /Users/ユーザー名/PythonProjects/sample_venv/lib/python3.8/site-packages (from requests<3.0.0dev,>=2.18.0->google-api-core<2dev,>=1.21.0->google-api-python-client) (2.10)
Installing collected packages: cachetools, pyasn1, pyasn1-modules, rsa, google-auth, packaging, protobuf, googleapis-common-protos, google-api-core, httplib2, uritemplate, google-auth-httplib2, google-api-python-client
Successfully installed cachetools-4.2.1 google-api-core-1.26.2 google-api-python-client-2.0.2 google-auth-1.28.0 google-auth-httplib2-0.1.0 googleapis-common-protos-1.53.0 httplib2-0.19.0 packaging-20.9 protobuf-3.15.6 pyasn1-0.4.8 pyasn1-modules-0.2.8 rsa-4.7.2 uritemplate-3.0.1
(sample_venv) %

3. API リクエストを試してみる

単純にブラウザの URL バーから

まずは Python 関係なく、単純にブラウザの URL バーに下記の URL を入れてみます。(APIキーはご自分のを入れてください)

https://youtube.googleapis.com/youtube/v3/channels?part=snippet%2CcontentDetails%2Cstatistics&id=UC_x5XG1OV2P6uZZ5FSM9Ttw&key=APIキー

すると下記の JSON テキストが表示されました。ID「UC_x5XG1OV2P6uZZ5FSM9Ttw」の Google Developers チャンネルの情報が取れました。

Python での実行

同じことを Python でやろうとすると下記の様なコードになるそうです。(Google のサイト参照

import os

import googleapiclient.discovery

def main():
    # Disable OAuthlib's HTTPS verification when running locally.
    # *DO NOT* leave this option enabled in production.
    os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"

    api_service_name = "youtube"
    api_version = "v3"
    DEVELOPER_KEY = "API キー"

    youtube = googleapiclient.discovery.build(api_service_name, api_version, developerKey = DEVELOPER_KEY)

    request = youtube.channels().list( # channels().list
        part="snippet,contentDetails,statistics", # 取得したい情報の指定
        id="UC_x5XG1OV2P6uZZ5FSM9Ttw" # チャンネル ID を指定(複数も可)
    )
    response = request.execute()

    print(response)

if __name__ == "__main__":
    main()

「part」に渡しているのが取得するデータの種類です。この記事の最後に取得できる part のリストを載せておきます。

動画情報の場合は下記の通り。個人的に好きで見てた FF 7 リメイクのプレイ動画です。 動画ID「fdsaZ8EMR2U」で指定しています。

import os

import googleapiclient.discovery

def main():
    # Disable OAuthlib's HTTPS verification when running locally.
    # *DO NOT* leave this option enabled in production.
    os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"

    api_service_name = "youtube"
    api_version = "v3"
    DEVELOPER_KEY = "API キー"

    youtube = googleapiclient.discovery.build(
        api_service_name, api_version, developerKey = DEVELOPER_KEY)

    request = youtube.videos().list( # videos().list
        part="contentDetails", # 取得したい情報の指定
        id="fdsaZ8EMR2U" # 動画 ID を指定(複数も可)
    )
    response = request.execute()

    print(response)

if __name__ == "__main__":
    main()

動画情報の part の内下記は投稿主のみアクセスできるそうです。

  • fileDetails
  • processingDetails
  • suggestions

そして急上昇ランキングを取る場合はこう。動画 ID の指定は消して「chart="mostPopular"」、「regionCode="JP"」、「maxResults=50」 を追記します。

JP(日本)の mostPopular(急上昇ランキング)から 50 件のデータを取るという意味です。

import os

import googleapiclient.discovery

def main():
    # Disable OAuthlib's HTTPS verification when running locally.
    # *DO NOT* leave this option enabled in production.
    os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"

    api_service_name = "youtube"
    api_version = "v3"
    DEVELOPER_KEY = "API キー"

    youtube = googleapiclient.discovery.build(
        api_service_name, api_version, developerKey = DEVELOPER_KEY)

    request = youtube.videos().list(
        part="snippet,contentDetails,statistics", # 取得したい情報の指定
        chart="mostPopular", # chart に「mostPopular」を指定
        maxResults=50, # 最大件数
        regionCode="JP" # 地域コード
    )
    response = request.execute()

    print(response)

if __name__ == "__main__":
    main()

実行すると下記の様な内容の JSON テキストが取れるはずです。(実際は整形されていない状態)

{
  "kind": "youtube#videoListResponse",
  "etag": "jUM1iWDvm5ncH7VdFCrks9TZYQY",
  "items": [
    {
      "kind": "youtube#video",
      "etag": "jtNs4gdyS4wCzxvZKpEA0GbXJ0M",
      "id": "GOBeIaj7Ml0",
      "snippet": {
        "publishedAt": "2021-03-27T11:00:43Z",
        "channelId": "UCpOjLndjOqMoffA-fr8cbKA",
        "title": "【コムドット】生意気な後輩YouTuberと学校貸し切って本気でドロケイした結果【アバ溜りドット】",
        "description": "まだまだ道は開けない!!\n\nアバンティーズ\nhttps://www.youtube.com/user/avntisdouga\n\nコムドット \nhttps://www.youtube.com/channel/UCRxPrFmRHsXGWfAyE6oqrPQ\n\nフォーエイト とのドロケイ動画はこちらです!\nhttps://youtu.be/cbrQUkl6iD8\n\n動画がいいなと思っていただけたら高評価押してください!再生数よりもこちらを参考にして動画を作りたい!!そして少しでも面白いなと思っていただけたらぜひ【チャンネル登録】お願いします!\n\n水溜りボンドLINE公式アカウント!\nhttps://lin.ee/cVkWzGW\n最新情報不定期配信中!僕らからのメッセージも届きますよ!\nぜひ友だち登録してください!\n\nしゃべる!水溜りボンドLINEスタンプ\nhttps://00m.in/AcJcI\n水溜りボンドLINEスタンプ\nhttps://00m.in/2mzGU\n水溜りボンドのグッズはこちら!\nhttps://muuu.com/users/c7bf52c2b9fb5c5a\nおすすめでございます!!\n\n6年間1度も休まず毎日投稿しておりました!これからも少しでもみなさんが楽しんでいただければ幸いです。\n\n\n\n☆水溜りボンドを初めて知った方に是非見ていただきたい動画はこちら!☆\nhttps://www.youtube.com/watch?v=BvRvt6Nxny8\n\n●水溜りボンドの日常!僕らのサブチャンネルです。毎日比較的ゆったりやってます〜\nhttps://www.youtube.com/channel/UCaTFX7ckdowpnwHWcJGH2KQ\n\n\n●水溜りボンドのオールナイトニッポン0の詳細はこちらから\nぜひフォローお願いいたします!!\nhttps://twitter.com/mizuann0\n●限定動画や専用の絵文字など。チャンネルメンバーシップはこちらから!\nhttps://www.youtube.com/channel/UCpOjLndjOqMoffA-fr8cbKA/join\n\n◆Twitter\nカンタのアカウント\nhttps://twitter.com/kantamizutamari\nトミーのアカウント\nhttps://twitter.com/miztamari_nikki\n\n■インスタグラム\nカンタのアカウント\nhttps://bit.ly/2UckzeP\nトミーのアカウント\nhttps://www.instagram.com/tommymizutamaribond/\nーーーーーー\nよく使用している友人のBGM作曲者さん↓\nhttps://twitter.com/gt_k_2014?lang=ja\n素材提供 Music-Note.jp(ミュージックノート)\n他の楽曲提供:Production Music by http://www.epidemicsound.com\n素材提供 PIXTA\n\n#水溜りボンド\n#ドロケイ\n#コムドット",
        "thumbnails": {
          "default": {
            "url": "https://i.ytimg.com/vi/GOBeIaj7Ml0/default.jpg",
            "width": 120,
            "height": 90
          },
          "medium": {
            "url": "https://i.ytimg.com/vi/GOBeIaj7Ml0/mqdefault.jpg",
            "width": 320,
            "height": 180
          },
          "high": {
            "url": "https://i.ytimg.com/vi/GOBeIaj7Ml0/hqdefault.jpg",
            "width": 480,
            "height": 360
          },
          "standard": {
            "url": "https://i.ytimg.com/vi/GOBeIaj7Ml0/sddefault.jpg",
            "width": 640,
            "height": 480
          },
          "maxres": {
            "url": "https://i.ytimg.com/vi/GOBeIaj7Ml0/maxresdefault.jpg",
            "width": 1280,
            "height": 720
          }
        },
        "channelTitle": "水溜りボンド",
        "tags": [
          "水溜りボンド",
          "都市伝説",
          "検証",
          "実験",
          "科学",
          "お笑い",
          "面白",
          "面白い",
          "企画",
          "楽しい",
          "ワクワク",
          "カンタ",
          "トミー"
        ],
        "categoryId": "24",
        "liveBroadcastContent": "none",
        "defaultLanguage": "ja",
        "localized": {
          "title": "【コムドット】生意気な後輩YouTuberと学校貸し切って本気でドロケイした結果【アバ溜りドット】",
          "description": "まだまだ道は開けない!!\n\nアバンティーズ\nhttps://www.youtube.com/user/avntisdouga\n\nコムドット \nhttps://www.youtube.com/channel/UCRxPrFmRHsXGWfAyE6oqrPQ\n\nフォーエイト とのドロケイ動画はこちらです!\nhttps://youtu.be/cbrQUkl6iD8\n\n動画がいいなと思っていただけたら高評価押してください!再生数よりもこちらを参考にして動画を作りたい!!そして少しでも面白いなと思っていただけたらぜひ【チャンネル登録】お願いします!\n\n水溜りボンドLINE公式アカウント!\nhttps://lin.ee/cVkWzGW\n最新情報不定期配信中!僕らからのメッセージも届きますよ!\nぜひ友だち登録してください!\n\nしゃべる!水溜りボンドLINEスタンプ\nhttps://00m.in/AcJcI\n水溜りボンドLINEスタンプ\nhttps://00m.in/2mzGU\n水溜りボンドのグッズはこちら!\nhttps://muuu.com/users/c7bf52c2b9fb5c5a\nおすすめでございます!!\n\n6年間1度も休まず毎日投稿しておりました!これからも少しでもみなさんが楽しんでいただければ幸いです。\n\n\n\n☆水溜りボンドを初めて知った方に是非見ていただきたい動画はこちら!☆\nhttps://www.youtube.com/watch?v=BvRvt6Nxny8\n\n●水溜りボンドの日常!僕らのサブチャンネルです。毎日比較的ゆったりやってます〜\nhttps://www.youtube.com/channel/UCaTFX7ckdowpnwHWcJGH2KQ\n\n\n●水溜りボンドのオールナイトニッポン0の詳細はこちらから\nぜひフォローお願いいたします!!\nhttps://twitter.com/mizuann0\n●限定動画や専用の絵文字など。チャンネルメンバーシップはこちらから!\nhttps://www.youtube.com/channel/UCpOjLndjOqMoffA-fr8cbKA/join\n\n◆Twitter\nカンタのアカウント\nhttps://twitter.com/kantamizutamari\nトミーのアカウント\nhttps://twitter.com/miztamari_nikki\n\n■インスタグラム\nカンタのアカウント\nhttps://bit.ly/2UckzeP\nトミーのアカウント\nhttps://www.instagram.com/tommymizutamaribond/\nーーーーーー\nよく使用している友人のBGM作曲者さん↓\nhttps://twitter.com/gt_k_2014?lang=ja\n素材提供 Music-Note.jp(ミュージックノート)\n他の楽曲提供:Production Music by http://www.epidemicsound.com\n素材提供 PIXTA\n\n#水溜りボンド\n#ドロケイ\n#コムドット"
        },
        "defaultAudioLanguage": "ja"
      },
      "contentDetails": {
        "duration": "PT23M58S",
        "dimension": "2d",
        "definition": "hd",
        "caption": "false",
        "licensedContent": true,
        "contentRating": {},
        "projection": "rectangular"
      },
      "statistics": {
        "viewCount": "337770",
        "likeCount": "17557",
        "dislikeCount": "544",
        "favoriteCount": "0",
        "commentCount": "1650"
      }
    },
 

4. 抽出できる情報

確認できた範囲で、どの part にどんな項目が含まれているのか書き出しておきます。

チャンネル情報の part

part 名称配下の項目
auditDetails投稿主のみアクセス可
brandingSettingschannel, image
contentDetailsrelatedPlaylists
contentOwnerDetails
idチャンネル ID
localizations
snippettitle, description, customUrl, publishedAt, thumbnails, localized, country
statisticsviewCount, subscriberCount, hiddenSubscriberCount, videoCount
statusprivacyStatus, isLinked, longUploadsStatus, madeForKids
topicDetailstopicIds, topicCategories

動画情報の part

part 名称配下の項目
contentDetailsduration, dimension, definition, caption, licensedContent, contentRating, projection
fileDetails投稿主のみアクセス可
id動画 ID
liveStreamingDetailsactualStartTime, scheduledStartTime, concurrentViewers, activeLiveChatId
localizations
playerembedHtml
processingDetails投稿主のみアクセス可
recordingDetails
snippetpublishedAt, channelId, title, description, thumbnails, channelTitle, tags, categoryId, liveBroadcastContent, localized, defaultAudioLanguage
statisticsviewCount, likeCount, dislikeCount, favoriteCount, commentCount
statusuploadStatus, privacyStatus, license, embeddable, publicStatsViewable, madeForKids
suggestions投稿主のみアクセス可
topicDetailstopicCategories

チャンネル情報や動画情報をリクエストする際、一度に指定できる id の数は 50 までの様です。

【Django】static ファイルの配置と設定

プロジェクト単位かアプリケーション単位かで若干ファイルの配置場所と設定方法が違いますが、まずは settings.py の INSTALLED_APPS に「'django.contrib.staticfiles'」の記述があることを確認します。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles', # この記述があることを確認

    'sample_django_app.apps.SampleDjangoAppConfig'
]

プロジェクト単位で使う static の場合

プロジェクトフォルダ(manage.py がある階層)直下に「static」フォルダを作成し、ファイルを配置。

settings.py の「STATICFILES_DIRS」にパスを追加します。

STATICFILES_DIRS = [
    os.path.join(BASE_DIR,'static'),
]

アプリケーション単位で使う static の場合

アプリケーションフォルダ直下に「static」フォルダを作成し、ファイルを配置。

settings.py に「STATIC_URL = '/static/'」の記述があることを確認。

STATIC_URL = '/static/'

【mac】Django プロジェクトで PostgreSQL のデータベースを利用する(仮想環境内)

Python 仮想環境内で Django プロジェクト用データベースを PostgreSQL で作成し、Django プロジェクトと紐づける方法を書きます。

今回は例として「sample_db」というデータベース作成し、プロジェクトと紐づけます。

  1. PostgreSQL で新規のデータベースを作成
  2. Django プロジェクトとデータベースの紐付け
  3. 仮想環境で接続用モジュールをインストール

PostgreSQL で新規のデータベースを作成

PostgreSQL を起動し「sample_db」という名前のデータベースを作成します。

% brew services start postgresql
% createdb sample_db

「psql -l」でデータベースのリストを表示すると、「sample_db」が作成されたのが確認できます。

% psql -l
                                         List of databases
   Name    |      Owner       | Encoding | Collate | Ctype |           Access privileges           
-----------+------------------+----------+---------+-------+---------------------------------------
 postgres  | ユーザー名         | UTF8     | C       | C     | 
 sample_db | ユーザー名         | UTF8     | C       | C     | 
 template0 | ユーザー名         | UTF8     | C       | C     | =c/ユーザー名                  +
           |                  |          |         |       | ユーザー名=CTc/ユーザー名
 template1 | ユーザー名         | UTF8     | C       | C     | =c/ユーザー名                  +
           |                  |          |         |       | ユーザー名=CTc/ユーザー名
(4 rows)

ちなみにデータベースを削除したい場合は「dropdb sample_db」と入力します。

Django プロジェクトとデータベースの紐付け

Django プロジェクトの settings.py を変更し、先ほど新規作成したデータベースを紐付けます。

プロジェクト作成時に自動作成された settings.py の内容は下記の通り。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

これを下記の様に変更します。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'sample_db',
        'USER': os.environ.get('DB_USER'),
        'PASSWORD': os.environ.get('DB_PASSWORD'),
        'HOST': '',
        'PORT': '',
    }
}

仮想環境で接続用モジュールをインストール

Python で PostgreSQL データベースに接続するために、接続用ドライバのモジュールが必要となります。もっとも多く使われている psycopg2 というモジュールをインストールします。

仮想環境に入った状態で「pip install psycopg2-binary」を実行します。

(sample_venv) % pip install psycopg2-binary
Collecting psycopg2-binary
  Downloading https://files.pythonhosted.org/packages/2c/85/c26507efb110f5a91f503e517f1db55f12ebecb001ff224b2cea234a07ef/psycopg2_binary-2.8.6-cp38-cp38-macosx_10_9_x86_64.macosx_10_9_intel.macosx_10_10_intel.macosx_10_10_x86_64.whl (1.5MB)
     |████████████████████████████████| 1.5MB 7.1MB/s 
Installing collected packages: psycopg2-binary
Successfully installed psycopg2-binary-2.8.6
WARNING: You are using pip version 19.2.3, however version 21.0.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
(sample_venv) % 

ちなみに

PyCharm の runserver を実行した時に下記のエラーが出て一瞬焦りましたが、PostgreSQL を起動したら治りました。

django.db.utils.OperationalError: could not connect to server: No such file or directory

ちなみのちなみに、settings.py の「DATABASES」の部分をコメントアウトなどするとデータベースを起動していなくても問題なく runserver を実行できます。

【mac】Python 仮想環境に Django プロジェクトと Django アプリケーションを作成する

  1. Django プロジェクトの作成
  2. Django アプリケーションの作成
  3. アプリケーションをプロジェクトに登録
  4. 動作確認
  5. 管理ユーザーの作成

Django プロジェクトの作成

仮想環境に入った状態で下記を実行します。今回例として仮想環境内に「Django_Project」フォルダを作ったのでその中に「sample_django_project」という名前の Django プロジェクトを作成します。

(sample_venv) % cd Django_Project
(sample_venv) Django_Project % django-admin startproject sample_django_project

すると下記の様に「Django_Project」フォルダの配下に「sample_django_project」フォルダとファイルが一式作成されます。

Django アプリケーションの作成

上の画像「manage.py」がある階層へ移動します。

(sample_venv) % cd sample_django_project

そして下記を実行して「sample_django_app」という名前で Django アプリケーションを作成します。

(sample_venv) sample_django_project % python manage.py startapp sample_django_app

すると、「sample_django_project」というプロジェクトの配下に「sample_django_app」が作成されました。

アプリケーションをプロジェクトに登録

アプリケーションフォルダの apps.py を開くと下記の通り「SampleDjangoAppConfig」というクラスがあるので、これをプロジェクトの settings.py に登録します。

from django.apps import AppConfig


class SampleDjangoAppConfig(AppConfig):
    name = 'sample_django_app'

settings.py の INSTALLED_APPS のリストに下記の通り「アプリケーション名.apps.クラス名」の形で追記します。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'sample_django_app.apps.SampleDjangoAppConfig'
]

これで Django プロジェクトと Django アプリケーションの作成は完了です。

動作確認

ターミナルでコマンド「python manage.py runserver」を実行し、動作確認をします。

% python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
April 23, 2021 - 21:27:24
Django version 3.2, using settings 'sample_django_project.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

特に問題がなければ上記の様なログが表示されるはずです。

そしてブラウザの URL バーに「http://127.0.0.1:8000/」と入力して下記の画面が表示されたら OK です。

管理ユーザーの作成

仮想環境内、「manage.py」のある階層でコマンド「python manage.py createsuperuser」を実行します。

% python manage.py createsuperuser

するとユーザー名、メールアドレスをパスワードを設定する様促されるので設定を行います。

Username : adminuser #任意のユーザー名
Email address: xxxxxxxx@gmail.com
Password: 
Password (again): 
Superuser created successfully.
% python manage.py runserver

ブラウザで「http://127.0.0.1:8000/admin/」にアクセスすると、管理ユーザーのログイン画面が表示されます。

ログインすると下記の通り管理ユーザー用画面が表示されます。

Mac で Python 仮想環境に Django をインストールしたい

Python の仮想環境を作る

仮想環境を作成したいディレクトリへ行き、下記のコマンドを実行します。例として「sample_virtual_environment」という仮想環境を作ります。

 python3 -m venv sample_virtual_environment

すると下記の様に Python の実行に必要なファイルやフォルダが一式作成されます。

これで仮想環境の作成は完了です。実際に仮想環境「sample_virtual_environment」を起動するには下記を実行します。

% cd sample_virtual_environment/bin
% source activate

下記の様にカッコの中に仮想環境の名前が表示されると思います。

(sample_virtual_environment) %

仮想環境から出たい場合は「deactivate」を実行します。

(sample_virtual_environment) % deactivate
%

Django をインストールする

仮想環境で Django をインストールするには、仮想環境を activate した状態で下記を実行します。

(sample_virtual_environment) % pip install django

下記のようなログが表示されて最後の方に「Successfully installed」と出ていれば成功です。

(sample_virtual_environment) % pip install django
Collecting django
  Downloading https://files.pythonhosted.org/packages/b8/6f/9a4415cc4fe9228e26ea53cf2005961799b2abb8da0411e519fdb74754fa/Django-3.1.7-py3-none-any.whl (7.8MB)
     |████████████████████████████████| 7.8MB 337kB/s 
Collecting asgiref<4,>=3.2.10 (from django)
  Downloading https://files.pythonhosted.org/packages/89/49/5531992efc62f9c6d08a7199dc31176c8c60f7b2548c6ef245f96f29d0d9/asgiref-3.3.1-py3-none-any.whl
Collecting sqlparse>=0.2.2 (from django)
  Downloading https://files.pythonhosted.org/packages/14/05/6e8eb62ca685b10e34051a80d7ea94b7137369d8c0be5c3b9d9b6e3f5dae/sqlparse-0.4.1-py3-none-any.whl (42kB)
     |████████████████████████████████| 51kB 9.6MB/s 
Collecting pytz (from django)
  Downloading https://files.pythonhosted.org/packages/70/94/784178ca5dd892a98f113cdd923372024dc04b8d40abe77ca76b5fb90ca6/pytz-2021.1-py2.py3-none-any.whl (510kB)
     |████████████████████████████████| 512kB 8.1MB/s 
Installing collected packages: asgiref, sqlparse, pytz, django
Successfully installed asgiref-3.3.1 django-3.1.7 pytz-2021.1 sqlparse-0.4.1
WARNING: You are using pip version 19.2.3, however version 21.0.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
(sample_virtual_environment) %

以上で Django のインストールは完了です。続けて Django プロジェクトそして Django アプリケーションの作成はこちらの記事へ。