1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

pythonで作るネットショップ django-oscarを始めよう ③商品追加~カスタマイズ発展編

Last updated at Posted at 2024-10-06

#はじめに

django-oscar入門の第三回目です。

oscarでカスタマイズを繰り返せば、私が開発したOriginallyTeeのような、C2CのECサイトを作ることまでできます。

例 カタログのカスタマイズ

前回はシンプルなカスタマイズを行いました。もう少し複雑な例も説明します。

モデル、テンプレート、ビューに横断するカスタマイズを行います。

以下のドキュメント+αで説明します。

catalogueアプリのフォーク

フォークの方法は前回と同じです。

$ python manage.py oscar_fork_app catalogue yourappsfolder
Creating package yourappsfolder\catalogue
Creating admin.py
Creating app config
Creating models.py
Creating migrations folder
Replace the entry 'oscar.apps.catalogue.apps.CatalogueConfig' with 'yourappsfolder.catalogue.apps.CatalogueConfig' in INSTALLED_APPS

settings.pyのINSTALLED_APPSを修正します。

settings.py

INSTALLED_APPS = [

#...

# 'oscar.apps.catalogue.apps.CatalogueConfig', 
'yourappsfolder.catalogue.apps.CatalogueConfig', #追加

モデル(models.py)のカスタマイズ

商品ページに動画リンクを追加したいケースとします。商品モデルへvideo_urlフィールドを追加します。

PracticeOscar\Lib\site-packages\oscar\apps\catalogue\abstract_models.py

のAbstractProductに、商品のモデル発見しました。

AbstractProductにフィールド追加するため、models.pyを書き換えます。

yourproject/catalogue/models.py

from django.db import models
from oscar.apps.catalogue.abstract_models import AbstractProduct

class Product(AbstractProduct):
    video_url = models.CharField(max_length=128, blank=True)
    
from oscar.apps.catalogue.models import *

Djangoのモデルのコードですが

以下の2点に注意して下さい。

1. oscar.apps.catalogue.abstract_models.pyからインポートする
2. oscar.apps.catalogue.models.pyのインポートを「最後」にする

  1. oscarはabstract_models.pyでモデルを定義して、models.pyでそのモデルを読み込みます。よってabstract_models.pyをインポートして上書きします

  2. 同名のモデルが存在する場合は、先に存在するモデルのみ読み込みます。よってこちらで上書きしたモデルを先に読み込むため、models.pyのインポートを最後にしています

モデル更新をデータベースに反映させます。

$ python manage.py makemigrations catalogue
$ python manage.py migrate

python manage.py runserver でサーバーにアクセスして、admin/catalogue/product/を見ると、商品モデルに新しいフィールドが追加されていますね。

※こちらはdjangoのデフォルトの管理画面で、oscarの管理画面のダッシュボードとは違うページなことに注意してください。両方使います。

せっかくなので 適当なリンクを記入して保存しておきましょう。

FireShot Capture 015 - テスト商品 - 商品 を変更 - Django サイト管理 - 127.0.0.1.png

テンプレート(.html)のカスタマイズ

先のリンクを商品名の下に表示したいケース考えます。

テンプレートファイルの上書きは

  1. 同名のテンプレートファイルを作成してから
  2. djangoのテンプレート継承を行います

FireShot Capture 012 - テスト商品 - Oscar - - 127.0.0.1.png

ここもフレームワーク側での該当するコード探しからスタートです。

テンプレートファイルは、仮想環境名PracticeOscarのとき

PracticeOscar\Lib\site-packages\oscar\templates\oscar

以下に存在します。これ以下のディレクトリはアプリによって分割されていますので、商品のテンプレートはcatalogue以下を探します。

PracticeOscar\Lib\site-packages\oscar\templates\oscar\catalogue\

さらに今回の修正は、商品の詳細ページの修正なので

PracticeOscar\Lib\site-packages\oscar\templates\oscar\catalogue\detail.html

の修正であることが分かります。

テンプレートの配置が分かったので、このディレクトリ構成を開発環境でも再現します。

ルート直下にtemplatesディレクトリを作成します。templates以下に修正したい全てのテンプレートを配置することになります。

そしてtemplates以降がフレームワーク側と同じになるように作成してください。

$ mkdir -p templates/oscar/catalogue
$ touch templates/oscar/catalogue/detail.html

以下はdjangoのテンプレート継承のコードとなります。

今回は{% block product_main %}{% endblock %}内の元のコードにaタグを追加することで、コードが変更されています。

この仕組みにより、少ないコード量で上書きできます。

templates/oscar/catalogue/detail.html

{% extends "oscar/catalogue/detail.html" %}

{% load history_tags %}
{% load currency_filters %}
{% load reviews_tags %}
{% load product_tags %}
{% load display_tags %}
{% load i18n %}
{% load purchase_info_tags %}

{% block product_main %}
<div class="col-sm-6 product_main">
    {% comment %}
        This is a bit clunky here.  Better to have some kind of JS-driven dashboard menu that
        pops out when clicked.  A bit like the Django-Debug-Toolbar button
    {% endcomment %}
    {% if user.is_staff %}
        <a class="float-right d-none d-md-block" href="{% url 'dashboard:catalogue-product' pk=product.id %}">
            <small><i class="fas fa-pencil-alt"></i> {% trans "Edit this product" %}</small>
        </a>
    {% endif %}
    <h1>{{ product.get_title }}</h1>
    <a href="{{ product.video_url }}" alt="youtube" target="_blank" rel="noopener noreferrer">動画リンク</a>
    {% block product_stock_record %}
        {% include "oscar/catalogue/partials/stock_record.html" with verbose=1 %}
    {% endblock %}

    {% iffeature "reviews" %}
        {% include "oscar/catalogue/reviews/partials/review_stars.html" %}
    {% endiffeature %}

    <hr/>

    {% if not product.is_parent %}
        {% block product_basket_form %}
            {% include "oscar/catalogue/partials/add_to_basket_form.html" %}
        {% endblock %}
    {% else %}
        {% block variants %}
            <h2>{% trans 'Variants:' %}</h2>
            {% for child in product.children.public %}
                {% purchase_info_for_product request child as child_session %}
                {% if child_session.availability.is_available_to_buy %}
                    <a href="{{ child.get_absolute_url }}">{{ child.get_title }}</a><br>
                {% endif %}
            {% endfor %}
        {% endblock %}
    {% endif %}
</div><!-- /col-sm-6 -->
{% endblock %}

FireShot Capture 016 - テスト商品 - Oscar - - 127.0.0.1.png

以上がテンプレートの継承になります。

まとめると

1. フレームワーク側でテンプレートファイルを見つける

2. 開発環境側のtemplatesディレクトリ以下に、ディレクトリ構成が同じになるようにテンプレートファイル設置する

3. djangoのテンプレート継承で、上書きしたい部分のみコードを修正する

3.はdjangoの機能ですので、今回もカスタマイズしたい部分のコードを素早く見つけられるかが重要となります。

ビュー(views.py)のカスタマイズ

リンクが存在するときのみ、リンクテキストを表示することを考えます。

商品詳細のビューの上書きを考えます。今回も該当のコード探しからスタートです。

PracticeOscar\Lib\site-packages\oscar\apps\catalogue\views.py

のProductDetailViewに、ビューがあることを見つけました。

views.pyを作成します。

$ touch yourappsfolder\catalogue\views.py 

ProductDetailViewを修正するため、views.pyのget_context_dataを以下のように書き換えます。

djangoのクラスビューのメソッド、get_context_dataを上書きする典型処理です。

yourappsfolder\catalogue\views.py

from oscar.core.loading import get_class

CoreProductDetailView = get_class("catalogue.views", "ProductDetailView")


class ProductDetailView(CoreProductDetailView):
    
    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        if ctx["product"].video_url:
            ctx["video_name"] = "動画リンクはこちら"
        else:
            ctx["video_name"] =""
        return ctx

先のテンプレートのaタグも修正します。

templates/oscar/catalogue/detail.html
{% comment %}
<a href="{{ product.video_url }}" alt="youtube" target="_blank" rel="noopener noreferrer">動画リンク</a>
を以下のように修正
{% endcomment %}

<a href="{{ product.video_url }}" alt="youtube" target="_blank" rel="noopener noreferrer">{{ video_name }}</a>

これでリンクの表示が動的に変更されるようになりました。

次回予定

今回はモデル(models.py)、テンプレート(.html)、ビュー(views.py)のカスタマイズ方法を説明しました。

同様の方法でフォーム(forms.py)等の他のファイルのカスタマイズもできますので、大半のカスタマイズはできるようになりました。

次はurlディスパッチャのカスタマイズとなります。

便利なWebサイト

github
https://github.com/django-oscar/django-oscar

ドキュメント 最初のうちはここを見ることが一番多いと思います
https://django-oscar.readthedocs.io/en/latest/

フォーラム 過去の質問を見ることもできます
https://groups.google.com/g/django-oscar
https://app.slack.com/client/T1QSP0999/C1QUF61T3

oscarはdjangoで作られているので、開発時はこちらも参照します
https://github.com/django/django
https://docs.djangoproject.com/en/5.0/

1
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?