読んだPythonのEコマース記事はどれも同じ構造:フレームワークをリストアップし、機能...

これはより実践的なアプローチです。実際に重要な決定事項をカバーします — 実際の根拠に基づくフレームワーク選択、一見簡単そうで難しい機能、知っておく価値のあるコードパターン、そして後で修正するより最初に避けた方がはるかに簡単なアーキテクチャの落とし穴です。


ここから始める:本当にカスタム構築すべきか?

フレームワークの議論より前に — Eコマース要件が標準的(商品カタログ、カート、チェックアウト、Stripe決済、注文管理)であれば、そもそも構築する必要があるかどうかを検討してください。Shopify、WooCommerce、またはSaleorのホスト型サービスでも、メンテナンス負担を抑えつつより早く市場投入できるかもしれません。

カスタムPythonが理にかなうケース:

  • 商品モデルが特殊(構成可能商品、バンドル、サブスクリプション、複雑な配信を伴うデジタル商品)
  • マルチベンダーマーケットプレイスを構築する場合
  • 既存のバックエンドサービスとの深い統合が必要な場合
  • MLを活用した機能(レコメンデーション、ダイナミックプライシング、需要予測)を追加し、同じコードベースに統合したい場合

Shopifyがなぜ使えないのかを明確に説明できない場合、間違った問題を解決している可能性があります。


フレームワーク比較:率直なバージョン

Django

Djangoは正しいデフォルトです。すべての観点で最高だからではなく、コマースに適した問題を最初から解決してくれるからです:

  • マイグレーション付きORM → 商品・注文モデルが最初からバージョン管理される
  • 管理インターフェース → 運用チームがコードに触れずに在庫・注文・顧客を管理可能
  • 組み込み認証 → ユーザー登録、ログイン、セッション、権限
  • フォーム処理とCSRF保護 → セキュリティの基礎が処理済み
# Django model for a basic product — you get admin, ORM queries, migrations for free
from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=255)
    slug = models.SlugField(unique=True)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    stock = models.PositiveIntegerField(default=0)
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-created_at']

    def is_in_stock(self):
        return self.stock > 0

Enter fullscreen mode Exit fullscreen mode

このモデルは即座にクエリ可能で、管理画面に即座に表示され、即座にマイグレーション可能です。これがDjangoの価値提案です。

Flask

Flaskは意図的なミニマリズムの選択であり、デフォルトではありません。ルーティングとリクエスト処理が得られます。それ以外 — ORM、認証、フォームバリデーション、キャッシング、管理画面 — は自分で追加するライブラリです。

# Flask requires you to wire everything manually
from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager

app = Flask(__name__)
db = SQLAlchemy(app)
login_manager = LoginManager(app)

# You're assembling pieces; Django ships them assembled

Enter fullscreen mode Exit fullscreen mode

Flaskが理にかなうのは、既存サービス上の薄いAPIレイヤーを構築する場合、または「Eコマースプラットフォーム」が既存の独自バックエンドロジックの上に構築された特殊なチェックアウトフローである場合です。そのようなケースでは、Djangoの意見を必要とせず、自分で構成したいでしょう。

Saleor

SaleorはDjangoベースのGraphQL優先Eコマースフレームワークです。本当に本番環境対応で、決済処理、マルチカレンシーサポート、商品カタログ、Reactベースのダッシュボードが付属しています。

トレードオフ:Saleorのデータモデルを継承することになります。要件が適合する場合、大きな頭出しになります。適合しない場合、フレームワークと協調するのではなく、フレームワークに逆らう作業になります。

要件が標準的なコマースドメイン内であり、迅速に進めたい場合に評価する価値があります。

Oscar

Oscarはもう一つのDjango Eコマースフレームワークで、データモデルのカスタマイズという点ではSaleorより柔軟です。「オーバーライドしてカスタマイズ」ではなく「フォークしてカスタマイズ」するモデルとして設計されています。

# Oscar setup
pip install django-oscar
# Fork the app you want to customize
python manage.py oscar_fork_app catalogue myshop/

Enter fullscreen mode Exit fullscreen mode

Oscarの商品抽象化(商品クラス、属性、バリアント)は、スキーマ変更を必要とせずに幅広い商品構造を処理します。複雑なカタログに適しています。


8つのコア機能 — 実際に難しいもの

1. 商品管理

シンプルなカタログであれば簡単です。以下のものがある場合、すぐに複雑になります:

  • 商品バリアント(サイズ×カラーの組み合わせ)
  • 構成可能商品(カスタム刻印、バンドルオプション)
  • 配信メカニズムを伴うデジタル商品
  • 異なる税制や配送プロファイルを持つ商品

Oscarの商品モデルはバリアントを最初からうまく処理します。生のDjangoを使用する場合、実際のデータを持つ前に商品スキーマを慎重に設計してください — 在庫を持つ商品モデルのマイグレーションは困難です。

2. 認証とセキュリティ

Djangoの認証システムは堅牢です。コマース特有には以下を追加します:

# settings.py — minimum security baseline for an e-commerce platform
AUTH_PASSWORD_VALIDATORS = [
    {'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 
     'OPTIONS': {'min_length': 10}},
    {'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator'},
]

SESSION_COOKIE_SECURE = True       # HTTPS only
CSRF_COOKIE_SECURE = True
SECURE_HSSL_REDIRECT = True
X_FRAME_OPTIONS = 'DENY'

Enter fullscreen mode Exit fullscreen mode

管理者アクセス用の2要素認証(django-two-factor-auth)、ログインログのレート制限、GDPR/CCPAコンプライアンスのための適切なPII処理はすべて必要な追加機能です。

3. ショッピングカートとチェックアウト

見た目より複雑です。直面するカート状態の問題:

  • ログイン時にゲストカートを認証済みユーザー・カートとどのようにマージするか?
  • チェックアウト中の在庫予約をどのように扱うか(ソフトリザーブ vs ハードリザーブ)?
  • セッション中に商品が在庫切れになった場合、カートはどうなるか?

チェックアウトが標準的であれば、SaleorまたはOscarのチェックアウトパイプラインから始めてください。これらのエッジケースはすでに検討されています。

4. 決済統合

Stripeは新規構築の正しいデフォルトです。Python SDKはよくメンテナンスされています:

import stripe
stripe.api_key = settings.STRIPE_SECRET_KEY

def create_payment_intent(amount_cents, currency, metadata):
    return stripe.PaymentIntent.create(
        amount=amount_cents,
        currency=currency,
        metadata=metadata,
        automatic_payment_methods={"enabled": True},
    )

Enter fullscreen mode Exit fullscreen mode

正しくすべきことは、どのゲートウェイを使うかではなく、決済状態モデルです。決済フローには一見したよりも多くのエッジケースがあります(失敗した請求、部分返金、異議申し立て、順序不同で到着するWebhook)。Webhook履歴から推測するのではなく、決済状態を明示的にモデル化してください。

5. 注文管理

運用上のバックボーンです。基本的なステータスライフサイクル以外に、返品・返金、注文編集、フルフィルメント統合が必要です。DjangoのORMにより、データモデリングがクリーンになります:

class Order(models.Model):
    class Status(models.TextChoices):
        PENDING = 'pending', 'Pending'
        CONFIRMED = 'confirmed', 'Confirmed'
        PROCESSING = 'processing', 'Processing'
        SHIPPED = 'shipped', 'Shipped'
        DELIVERED = 'delivered', 'Delivered'
        CANCELLED = 'cancelled', 'Cancelled'
        REFUNDED = 'refunded', 'Refunded'

    user = models.ForeignKey(User, on_delete=models.PROTECT)
    status = models.CharField(max_length=20, choices=Status.choices, default=Status.PENDING)
    total = models.DecimalField(max_digits=10, decimal_places=2)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

Enter fullscreen mode Exit fullscreen mode

6. 検索とフィルタリング

Django ORMはシンプルなフィルタリングを処理します。それ以上の場合、最初から本物の検索エンジンを統合してください:

# Elasticsearch via elasticsearch-dsl-py
from elasticsearch_dsl import Document, Text, Keyword, Float

class ProductIndex(Document):
    name = Text(analyzer='english')
    category = Keyword()
    price = Float()

    class Index:
        name = 'products'

Enter fullscreen mode Exit fullscreen mode

TypesenseはPythonサポートが良く、セルフホスティングが大幅に容易な軽量な代替手段です。これを後付けで追加しないでください — 既存のデータパイプラインに検索インフラを後付けするのは、最初から構築するよりも困難です。

7. 非同期タスク — 必要になる前にセットアップする

これはほとんどの機能リストに含まれませんが、含まれるべきです。メール送信、Webhook処理、在庫更新、検索インデックス更新、レポート生成 — これらはリクエストサイクル内で同期的に実行すべきではありません:

# Celery task for order confirmation email
from celery import shared_task
from django.core.mail import send_mail

@shared_task
def send_order_confirmation(order_id):
    order = Order.objects.get(id=order_id)
    send_mail(
        subject=f'Order #{order.id} confirmed',
        message=render_confirmation_email(order),
        from_email=settings.DEFAULT_FROM_EMAIL,
        recipient_list=[order.user.email],
    )

Enter fullscreen mode Exit fullscreen mode

Celery + Redisが標準的なセットアップです。最初に導入してください。後から追加すると、現在同期的に実行している遅い操作をコードベースのすべての場所で修正することになります。

8. SEO

Djangoはここで本当に優れています — クリーンなURLルーティング、簡単なメタタグ制御、組み込みのサイトマップ生成。django-metaが大部分の定型処理を処理します:

# SEO-friendly URL structure
urlpatterns = [
    path('shop/<slug:category_slug>/<slug:product_slug>/', views.product_detail, name='product-detail'),
]
# Produces: /shop/mens-shoes/nike-air-max-90/ — clean, descriptive, indexable

Enter fullscreen mode Exit fullscreen mode

商品バリアントの場合、重複コンテンツペナルティを避けるために正規URLを慎重に処理してください。


最初に下すべきアーキテクチャ決定

バックエンドコードを書く前にフロントエンドアーキテクチャを選択する。 Djangoテンプレート(サーバーサイドレンダリング) vs. Django REST Framework + Reactフロントエンドは、URLの構造化方法、認証の処理方法(セッションベース vs JWT)、モバイルへのページ配信方法を変えます。どちらも動作します — ただしプロジェクト途中でアプローチを混ぜるとコストがかかります。

商品スキーマを現在の状態ではなく、目指す状態に合わせてモデル化する。 バリアント、バンドル、または複数の商品タイプを持つ可能性がある場合、その柔軟性を組み込んでください。Oscarを使用しなくても、Oscarの商品抽象化を研究する価値があります。

初日から非同期タスクをセットアップする。 Celery + Redis。これを延期しないでください。

検索インフラを最初にセットアップする。 ElasticsearchまたはTypesense。後からボルトオンしないでください。


クイックリファレンス:フレームワーク選択

状況 推奨
標準的なコマース、迅速な進行が必要 Saleor
複雑なカタログ、柔軟性が必要 Oscar
標準的なコマース、グリーンフィールド、完全な制御 Django
既存サービス上の薄いAPIレイヤー Flask
いたるところに非標準要件がある Djangoをゼロから

Innostaxでは、さまざまな規模のPython Eコマースプラットフォームをリリースしてきました。 コマース構築のためのフレームワーク選択やアーキテクチャについて検討中の方は、こちらからお問い合わせください — 喜んで一緒に考えます。

元々は Innostax Engineering Blog で公開されました。