プロジェクト作成は頻度が低く都度調べてしまうので、コピペ用と、順番で抜け漏れでないようにするためのメモです。
他の言語・フレームワークから乗り換えて利用する方にはそこそこ有益かもしれません。
- プロジェクト作成から基本設定
- 基本プラグインの導入
- 管理画面テンプレート導入(AdminLTE)
- アカウント系アプリケーションの追加とカスタムユーザーモデル
- よく使うテンプレまとめ
プロジェクト作成から基本設定
- プロジェクト作成
- staticルート設定
- テンプレートフォルダ設定
- データベース設定
- ローカライゼーション設定
- キャッシュのデータベース化設定
プロジェクト作成
django-admin startproject [プロジェクト名]
staticルート設定
staticルートフォルダを設定しておきます。webから直接アクセスできるフォルダです。
STATIC_URL='static/'
STATIC_ROOT = os.path.join(BASE_DIR, "static")
テンプレートフォルダ設定
テンプレートフォルダは各アプリケーションの下にtemplatesフォルダを作ってそこに配置するように説明しているサイトが多いのですが、プロジェクトフォルダ直下のtemplatesフォルダを用意して、全体で使うテンプレートはこちらに配置するようにします。
TEMPLATES = [
...
'DIRS': [
os.path.join(BASE_DIR, 'templates'),
],
データベース変更
とりあえずmysqlとpostgresの記述をコピペできるように。
DATABASES = {
'default': {
# mysqlの場合
'ENGINE': 'django.db.backends.mysql',
'PORT': '3306',
# Postgresの場合
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'PORT': '5432',
# 共通
'NAME': 'your db name',
'USER': 'user',
'PASSWORD': 'password',
'HOST': 'localhost',
}
}
ローカライゼーション設定
セッションミドルウェアの後に、ロケールミドルウェアを追加してローカライゼーションファイルを作成するフォルダを作っておきます。多言語対応しないとしても、リソースを外部ファイルにするという観点から基本的に全部のプロジェクトでやるようにします。
settings.pyのimportにローカライゼーション用のgettext_lazyとosを追加しておきます。
import os
from django.utils.translation import gettext_lazy as _
ミドルウェア追加。セッションミドルウェアの後にLocaleMiddlewareを追加します。
MIDDLEWARE = [
...
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
...
]
ローカライゼーションの言語ファイルを配置するフォルダの設定と作成をしておきます。
LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'
USE_I18N = True
USE_TZ = True
LANGUAGES = [
('en', _('English')),
('ja', _('Japanese')),
]
LOCALE_PATHS = (
os.path.join(BASE_DIR, 'locale'),
)
フォルダ作成
mkdir -p locale/ja/LC_MESSAGES
urls.pyのURLパターンにi18n_patternsをインポートして適用しておきます。
from django.conf.urls.i18n import i18n_patterns
# urlpatterns = [
# ...
#]
urlpatterns = i18n_patterns(
...
prefix_default_language=False
)
キャッシュ利用設定
テンプレートやページのキャッシュについては後で本番化で検討で良いのですが、プログラム中で何かとキャッシュを使う機会は多いものですので、基本的に全てのプロジェクトで、まずはデータベースのキャッシュテーブルに保存するようにしておきます。パフォーマンスが必要な場合はmemcachedやradisを使う方が良いのですが、ローカル開発や新規webアプリケーションの場合はこのままで。
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'キャッシュテーブル名',
}
}
必須プラグインの導入
インストール
よく使うプラグインをとりあえず入れておきます。この4つは使わないことはあまりないかと思います。
- environ ... 設定の外部ファイル化(必須)
- django_boost ... データモデルの論理削除導入
- django-mathfilter ... テンプレートで算術演算するためのフィルタ
- sorl-thumbnail ... アップロード画像のサムネイルを簡単生成
pipコマンドでローカルインストールしておきます。
pip install environ
pip install django_boost
pip install django-mathfilters
pip install sorl-thumbnail
設定ファイル変更
インストールしたら
アプリケーションフォルダに.envファイルを作成し
setting.pyのINSTALLED_APPSに追加した上で、
environで.envファイルから設定を読み込めるようにしておきます。
import os
import environ
...(略)...
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# envファイルのパスを追加
env = environ.Env()
env.read_env(os.path.join(BASE_DIR, '.env'))
...(略)...
# installed appsに追加
INSTALLED_APPS = [
...
'django_boost',
'mathfilters',
'stdimage',
]
environを入れたら、SECRET_KEY, DEBUG, データベース接続情報系は全てenvにこの段階で追い出しておいた方が良いです。
管理画面テンプレート導入
AdminLTE3を入れます。バージョンがやや古くBootstrap4で、5に対応していないため、Django Bootsrap5 Volt を入れるか悩みどころですが、AdminLTE3ならパッケージで入れられつつ、工数も少なく済むため、リソースや予算が潤沢でなければ管理画面はフロントエンドエンジニアを別リソースで絡められることはあまりないため、AdminLTEでそのままやります。
パッケージがインストールされていないならインストール。
pip install django-adminlte-3
インストール済みアプリにsetting.pyにadminlte3アプリとテーマを追加。
INSTALLED_APPS = [
...
'adminlte3',
'adminlte3_theme',
]
静的ファイルをプロジェクト内にコピー。
python manage.py collectstatic
アカウント系アプリケーションだけ切り分け - カスタムユーザークラス
必ずmigrationする前にやっておきましょう。後からユーザーモデルクラスを変更するとかなり面倒な手順が必要になってしまいます。
会員登録や会員の情報登録は割とよく使いまわせるものなので、accountアプリケーションだけ本体と別で最初に作ります。使いまわせるコードが手持ちである場合は追加したアプリケーションのコードを丸ごとコピーやgitのサブモジュールで持って来れたりします。
django-admin startapp account
新規にアカウント系の機能を作る場合はカスタムユーザーモデルの雛形だけ作成して、追加してDjango管理画面から操作できるようにしておきます。
CustomUserクラスのソースコードからコピペした下記コードをコピペして必要に応じて変更するのが楽です。以下のコードはローカライゼーションの設定が終わっていることが前提です。
from django.db import models
from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.auth.validators import UnicodeUsernameValidator
from django.contrib.auth.models import PermissionsMixin, UserManager
from django_boost.models.mixins import LogicalDeletionMixin
from django.utils.translation import gettext_lazy as _
from django.utils import timezone
from django.core.mail import send_mail
# Create your models here.
class User(AbstractBaseUser, PermissionsMixin, LogicalDeletionMixin):
username_validator = UnicodeUsernameValidator()
username = models.CharField(verbose_name=_("username"),max_length=150,unique=True,validators=[username_validator])
first_name = models.CharField(_("first name"), max_length=150, blank=True)
last_name = models.CharField(_("last name"), max_length=150, blank=True)
email = models.EmailField(_("email address"), blank=True)
date_joined = models.DateTimeField(_("date joined"), default=timezone.now)
is_staff = models.BooleanField(
_("staff status"),
default=False,
help_text=_("Designates whether the user can log into this admin site."),
)
is_active = models.BooleanField(
_("active"),
default=True,
help_text=_(
"Designates whether this user should be treated as active. "
"Unselect this instead of deleting accounts."
),
)
USERNAME_FIELD = "username"
EMAIL_FIELD = "email"
REQUIRED_FIELDS = []
objects = UserManager()
class Meta:
verbose_name = _("user")
verbose_name_plural = _("users")
def clean(self):
super().clean()
self.email = self.__class__.objects.normalize_email(self.email)
def get_full_name(self):
"""
Return the first_name plus the last_name, with a space in between.
"""
full_name = "%s %s" % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
"""Return the short name for the user."""
return self.first_name
def email_user(self, subject, message, from_email=None, **kwargs):
"""Send an email to this user."""
send_mail(subject, message, from_email, [self.email], **kwargs)
Djang管理画面から操作できるようにadmin.pyに上記モデルを追加しておきます。
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User
# Register your models here.
class CustomUserAdmin(UserAdmin):
list_display = ('username','first_name','last_name','email')
ordering = ('-date_joined',)
admin.site.register(User,CustomUserAdmin)
accountをsettings.pyのインストール済みアプリケーションに追加しておきます。上記のモデルでは論理削除を利用するdjango_boostを使っているので、django_boostも追加しておきます。
INSTALLED_APPS = [
...
'adminlte3',
'adminlte3_theme',
'django_boost',
'account.apps.AccountConfig',
]
settings.pyにユーザー認証モデルとして行を追加しておきます。ついでにログイン・ログアウト後のURLも追加します。
場所はどこでも大丈夫です。
# User model
AUTH_USER_MODEL = 'account.User'
# Login
LOGIN_URL = '/login'
LOGIN_REDIRECT_URL = '/'
LOGOUT_REDIRECT_URL='/login'
ソーシャルログイン導入(必要な場合のみ)
pip install social-auth-app-django
INSTALLED_APPS = [
...
'social_django',
]
MIDDLEWARE = [
...
'social_django.middleware.SocialAuthExceptionMiddleware',
]
...
AUTHENTICATION_BACKENDS = (
'social_core.backends.open_id.OpenIdAuth',
'social_core.backends.google.GoogleOpenId',
'social_core.backends.google.GoogleOAuth2',
'social_core.backends.github.GithubOAuth2',
'social_core.backends.twitter.TwitterOAuth',
'social_core.backends.facebook.FacebookOAuth2',
'social_core.backends.linkedin.LinkedinOAuth2',
'django.contrib.auth.backends.ModelBackend',
)
# ソーシャルログインキー/シークレット
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = env('SOCIAL_AUTH_GOOGLE_OAUTH2_KEY') # クライアントID
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = env('SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET') # クライアント シークレット
SOCIAL_AUTH_FACEBOOK_KEY = env('SOCIAL_AUTH_FACEBOOK_KEY') # アプリID
SOCIAL_AUTH_FACEBOOK_SECRET = env('SOCIAL_AUTH_FACEBOOK_SECRET') # app secret
SOCIAL_AUTH_TWITTER_KEY = env('SOCIAL_AUTH_TWITTER_KEY') # Consumer Key
SOCIAL_AUTH_TWITTER_SECRET = env('SOCIAL_AUTH_TWITTER_SECRET') # Consumer Secret
SOCIAL_AUTH_GITHUB_KEY = env('SOCIAL_AUTH_GITHUB_KEY') # Client ID
SOCIAL_AUTH_GITHUB_SECRET = env('SOCIAL_AUTH_GITHUB_SECRET') # Client Secret
SOCIAL_AUTH_LINKEDIN_OAUTH2_KEY = env('SOCIAL_AUTH_LINKEDIN_OAUTH2_KEY')
SOCIAL_AUTH_LINKEDIN_OAUTH2_SECRET = env('SOCIAL_AUTH_LINKEDIN_OAUTH2_SECRET')
マイグレーション
アカウント系のデータモデルの調整が終わってからマイグレーションします。キャッシュテーブルも作ります。
python manage.py createcachetable
python manage.py makemigrations
python manage.py migrate
管理者作成と稼働
python manage.py createsuperuser
python manage.py runserver