riceshop のプロジェクト全体で共有される基盤——Django 設定(config/settings.py)、全ページ共通の文脈を注入するコンテキストプロセッサ、共通テンプレートタグ、ベーステンプレート——を解説する開発者向けドキュメントです。
このドキュメントは旧
specs/30_共通基盤設定 実装手順書.md(Ver.3.1) を、現行のconfig/settings.py/cart/context_processors.py/dashboard/context_processors.py/common/templatetags/common_extras.py/templates/base.htmlと照合して再構成したものです。旧手順書との差異は本文中に「実装メモ」として注記しています。
設定は環境変数駆動です。冒頭で load_dotenv() を呼び、主要な値を os.getenv(...) で読み込みます(環境変数の供給経路は 開発環境構築 §3.1 を参照)。
| 設定 | 環境変数 | 備考 |
|---|---|---|
SECRET_KEY |
DJANGO_SECRET_KEY |
— |
DEBUG |
DJANGO_DEBUG |
文字列 'True' との一致で真偽を判定 |
ALLOWED_HOSTS |
DJANGO_ALLOWED_HOSTS |
カンマ区切り。下記のとおり DEBUG 時に追加あり |
CSRF_TRUSTED_ORIGINS |
DJANGO_CSRF_TRUSTED_ORIGINS |
カンマ区切り |
DATABASES['default'] |
MYSQL_DATABASE / MYSQL_USER / MYSQL_PASSWORD / MYSQL_HOST |
MySQL・charset=utf8mb4・ポート 3306 固定 |
DEBUG=True のとき ALLOWED_HOSTS に localhost / 127.0.0.1 / 0.0.0.0 を追加。DEBUG=False のときは localhost のみ追加します。実装メモ: 旧手順書では DEBUG 時の追加が
['localhost', '127.0.0.1']でしたが、現行コードは'0.0.0.0'も追加します(config/settings.py)。
標準アプリに加え、以下を利用します。
whitenoise.runserver_nostatic / django.contrib.staticfiles — 静的ファイル配信。django.contrib.humanize — 金額の桁区切り(intcomma 等)。bootstrap5(django-bootstrap-v5) — フォームレンダリング。django_extensions — 開発補助コマンド群(常時 有効)。accounts / products / orders / cart / system_settings / dashboard / mg_orders / mg_customers / mg_masters / mg_workflow / common(責務は design/アーキテクチャ 参照)。ミドルウェアは Django 標準構成で、先頭付近に SecurityMiddleware → whitenoise.middleware.WhiteNoiseMiddleware を置いています。
DEBUG=True のときだけ debug_toolbar を INSTALLED_APPS と MIDDLEWARE に追記し、INTERNAL_IPS をローカルホスト+(取得できれば)コンテナのゲートウェイ IP で構成します。TEMPLATES の DIRS はプロジェクト直下の templates/、APP_DIRS=True。標準のコンテキストプロセッサに加え、本プロジェクト独自のものを 3 つ登録しています。
'cart.context_processors.cart_context',
'dashboard.context_processors.bag_stock_summary',
'dashboard.context_processors.stock_summary',
これらは全テンプレートで利用可能な共通文脈を注入します(詳細は §2)。
LANGUAGE_CODE='ja' / TIME_ZONE='Asia/Tokyo' / USE_TZ=True。USE_THOUSAND_SEPARATOR=True / NUMBER_GROUPING=3 で数値の桁区切りを有効化。STATIC_URL='static/'、開発用ソースは STATICFILES_DIRS=[BASE_DIR/"static"]、収集先は STATIC_ROOT=BASE_DIR/"staticfiles"、ストレージは whitenoise.storage.CompressedManifestStaticFilesStorage。# --- My Settings ---)config/settings.py 末尾に、業務ロジックが参照する定数群があります。
| 設定 | 値 | 用途・参照先 |
|---|---|---|
AUTH_USER_MODEL |
accounts.User |
カスタムユーザー(→ features/アカウント認証) |
AUTHENTICATION_BACKENDS |
accounts.backends.IgnoreSpaceModelBackend |
ログイン ID のスペース無視照合(→ features/アカウント認証) |
LOGIN_URL / LOGIN_REDIRECT_URL / LOGOUT_REDIRECT_URL |
accounts:login / products:product_list / accounts:login |
認証導線 |
CART_SESSION_ID |
cart |
カートのセッションキー(→ features/購入者向け機能) |
CART_HYBRID_THRESHOLD |
3 |
カート UI の表示切替しきい値(cart_context 経由でテンプレートへ) |
NORMAL_SHIPPING_FEE / REMOTE_SHIPPING_FEE |
1200 / 1800 |
通常/離島等の送料(→ features/送料計算) |
SEIMAI_WEIGHT_COEFFICIENT |
1.1 |
精米の玄米換算係数(在庫消費・梱包重量計算) |
PACKAGE_MAX_WEIGHT_KG / DEFAULT_BOX_WEIGHT_KG |
20.0 / 0.5 |
1 箱の上限重量/箱自体の重量(→ features/送料計算) |
実装メモ:
AUTHENTICATION_BACKENDSは旧30手順書のsettings.pyには含まれていませんでした(旧構成では20_アカウント・認証機能手順書で追加する流れ)。現行コードには反映済みです。
DEBUG=False のとき、以下を有効化します(config/settings.py 末尾)。
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
リバースプロキシ(Traefik)配下での HTTPS 終端を前提とした設定です(→ operations/本番デプロイ)。
全テンプレートに共通文脈を注入する 3 つの関数です。アクセス制御の有無が関数ごとに異なる点に注意してください。
stock_summary / bag_stock_summary — 関数内でログイン状態・スタッフ判定を行い、対象外なら空辞書を返します。cart_context — アクセス制御を行わず常に注入します。画面上の露出はテンプレート側(user.is_authenticated 等)で制御されます。cart.context_processors.cart_contextカート(Cart)と cart_hybrid_threshold(= settings.CART_HYBRID_THRESHOLD)を常にテンプレートに提供します(ログイン状態やスタッフ判定はしません)。サイドバーやフローティングバーのカート表示、注文確認導線で利用され、表示可否はテンプレート側で制御されます(→ features/購入者向け機能)。
dashboard.context_processors.stock_summary(購入者向け)stock_summary として返します。Product.ProductType.SEIMAI)には SEIMAI_WEIGHT_COEFFICIENT を掛けて玄米換算します。dashboard.context_processors.bag_stock_summary(管理者向け)bag_stock_summary として返します。各行は次のフィールドを持ちます。total(必要数)は受付済み注文(Order.OrderStatus.ACCEPTED)の OrderItem 由来です。一方 prepared / packed / shipped は Bag.objects.filter(prepared=True) を商品単位で集計したもので、特定の受付済み注文・引当・宛先には限定されません(その商品の物理袋全体が対象)。| フィールド | 意味 |
|---|---|
total |
受付済み注文の必要数(OrderItem 合計) |
unbagged |
未袋詰(total − prepared、下限 0) |
bag_rice |
袋詰済みだが未梱包(prepared − packed、下限 0) |
boxed |
梱包済みだが未出荷(packed − shipped、下限 0) |
shipped |
出荷済み・配達済み(Package.PackageStatus.SHIPPED / DELIVERED) |
実装メモ: 旧手順書の
bag_stock_summaryはboxed(梱包済み総数)までで、出荷段階を区別していませんでした。現行コードはshipped_totalを集計し、boxedを「梱包済みだが未出荷」に再定義したうえでshippedを追加しています(dashboard/context_processors.py、出荷ワークフローと整合)。詳細は features/出荷ワークフロー を参照。
注意(丸めの影響):
unbagged/bag_rice/boxedはいずれもmax(0, …)で下限 0 に丸められます。prepared/packed/shippedは商品単位の物理袋全体の集計なので、過去に出荷済みの袋や余剰袋があると、これらの差分は厳密な「現在の工程内訳」と一致しないことがあります。
補足:
bag_stock_summaryは全テンプレートに注入されますが、表示は管理者向けベーステンプレートtemplates/base_management.html側で行います。一般向けベーステンプレート(templates/base.html)のサイドバーが直接使うのはstock_summaryとcartです。
common アプリは、プロジェクト横断で使う共通機能を置くための器です。現状はテンプレートタグのみを持ちます。
common/templatetags/common_extras.py:
@register.filter(name='get_item')
def get_item(dictionary, key):
"""テンプレートで辞書のキーから値を取得するためのフィルター"""
return dictionary.get(key)
get_item — テンプレート内で辞書のキー参照(dict[key] 相当)を可能にするフィルター。{% load common_extras %} の上で {{ mydict|get_item:key }} の形で使います。templates/products/product_list.html。全画面が継承する共通レイアウトです。レスポンシブ(PC は固定サイドバー、モバイルは offcanvas + フローティングカートバー)を CSS で切り替えます。共通基盤として押さえるべき責務は次のとおりです。
{% load humanize %} で金額の桁区切り(intcomma)を利用。stock_summary があれば在庫状況テーブル、PC では cart のご注文内容を表示。messages のレベル(40=danger / 30=warning / 25=success / その他=info)に応じて Bootstrap アラートに振り分け。manualModal と marked.min.js(CDN)+ static/js/manual.js を読み込み。本文は Markdown を fetch してクライアント側で描画します(→ features/管理者向け補助機能)。title / extra_css / sidebar_content / content / floating_bar_content / extra_js を子テンプレートが上書きします。元資料: specs/30_共通基盤設定 実装手順書.md (Ver.3.1) を現行コード(config/settings.py, cart/context_processors.py, dashboard/context_processors.py, common/templatetags/common_extras.py, templates/base.html)と照合して再構成
関連: README, specs棚卸し表, Issue #1