[PYTHON] Django Oscar (EC Package) Japan Usage Guide

Django, the (probably) most used full-stack web framework in Python. Oscar, (probably) the most vigorous e-commerce package that runs on Django.

I wrote the Oscar as a guide for using it in Japan.

Django-Oscar documentation: https://django-oscar.readthedocs.org/

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

Features of Oscar

--Since it runs on Python + Django environment, it is easy for experienced users to customize. --Works on Python3 --Django is ~~ latest ~~ 1.8 required. (Addition: 1.9 was released) --Modified BSD License (BSD 3-Clause License (Revised)). Same as Django. --With Bootstrap. It's responsive from the demo template. --Multilingual support. Japanese PO files are included from the beginning, but they are not so complete. --Multi-currency compatible. The currency type is a decimal number with a decimal point by default, so I was a little confused at first. --You can register addresses in various countries from the beginning. ――The payment system is not included at first, so you can either enter it with pip or write it yourself. --Flexible customization other than core code. For example, you can add fields to the model, change the behavior of the view, etc. without modifying the original code. (If you want to fix the core code, maybe a monkey patch or a repository fork ...) --The product (catalog) consists of three stages: class> product> inventory & price. --Inventory & charge classes can be set for each currency. --There is a category class. Category: Many products: Many ――The image of the product is usually uploaded from the site, and you cannot register the image in an external service and write only the URL in the model at first. Model customization and template modification required. --For tax rates, write the tax rate class in hard coding. --Style sheet is less --The administrator account that logs in to the management site and the general customer account will be created in the same model (table). Separate permissions by permission flag. If you want to separate this model, it seems quite difficult.

Functions included from the beginning

--Review function

Such.

It's relatively easy to turn off features such as reviews. (Available in settings)

By the way, the "point" function that is common in Japan is not included.

Model fork

If you want to extend (inherit) the standard Oscar function, use a function called fork.

First, create a directory such as oscar_fork (or myapps) directly under the project.

$ ./manage.py oscar_fork_app catalogue oscar_fork

If you execute, oscar_fork / catalog will be created.

In this fork module

--Model extension --Extending and disabling views --Add or disable URLs

And so on.

Additional example of model field

For example, if you want to add a thumbnail_url field to catalog.Product

oscar_fork/catalogue/models.py


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

class Product(AbstractProduct):
    image_url = models.URLField(default='', blank=True)
    thumbnail_url = models.URLField(default='', blank=True)

from oscar.apps.catalogue.models import *  # noqa

As INSTALLED_APPS

settings.py


INSTALLED_APPS = [
    'django.contrib.admin',
    ....
]
INSTALLED_APPS += get_core_apps([
    'oscar_fork.catalogue',
])

Extend INSTALLED_APPS by writing.

You can create a migration file with ./manage.py makemigrations, so use ./manage.py migrate to migrate the schema.

View extension

If you want to expand the view of your cart (checkout)

$ ./manage.py oscar_fork_app checkout oscar_fork

after

python:oscar_fork/checkout.views.py


from oscar.apps.checkout import views

class IndexView(views.IndexView):
    def get(self, request, *args, **kwargs):
        #get processing...

You can write like this.

Also added to INSTALLED_APPS

settings.py


INSTALLED_APPS += get_core_apps([
    'oscar_fork.catalogue',
    'oscar_fork.checkout',
])

Add and edit URLs

If you want to add or disable URLs, write app.py.

$ ./manage.py oscar_fork_app customer oscar_fork

oscar_fork/customer/app.py


from oscar.apps.customer import app

class CustomerApplication(app.CustomerApplication):
    def get_urls(self):
        urls = [
            # Login, logout and register doesn't require login
            url(r'^login/$', self.login_view.as_view(), name='login'),
            url(r'^logout/$', self.logout_view.as_view(), name='logout'),
            # url(r'^register/$', self.register_view.as_view(),
            # name='register'),

You can disable it by commenting out the register URL.

Also added to INSTALLED_APPS. (Details omitted)

How to use it for Japan

First, set Django settings for Japan.

settings.py


LANGUAGE_CODE = 'ja'

TIME_ZONE = 'Asia/Tokyo'

Oscar-specific settings for Japan

settings.py


OSCAR_DEFAULT_CURRENCY = 'JPY'

OSCAR_CURRENCY_FORMAT = '¤#,##0'

Registered country only in Japan

$ ./manage.py oscar_populate_countries

So, the country model (address_country) will contain the initial data for 249 countries.

If is_shipping_country is set to 1 for Japan only and 0 for others, the country name selection will not appear when registering an address (Japan will be the default).

From the Django shell or SQL.

mysql> UPDATE address_country SET is_shipping_country = 0 WHERE printable_name != 'Japan';

Write and translate PO files

How do I translate Oscar? — django-oscar 0.5 documentation https://django-oscar.readthedocs.org/en/releases-0.5/howto/how_do_i_translate_oscar.html

Refer to here

$ mkdir locale i18n
$ ln -s $PATH_TO_OSCAR i18n/oscar
$ ./manage.py makemessages --symlinks --locale=ja

(If that doesn't work, maybe gettext isn't installed. In my case (mac) I needed brew install gettext --force)

Edit locale / ja / LC_MESSAGES / django.po

msgid "email address"
msgstr "mail address"

msgid "First name"
msgstr "Surname"

msgid "Last name"
msgstr "Name"

msgid "View basket"
msgstr "See the cart"

msgid "Basket total"
msgstr "total fee"

msgid "Basket total:"
msgstr "total fee:"

msgid "In stock"
msgstr "In stock"

msgid "Shipping"
msgstr "Shipping"

msgid "Total"
msgstr "subtotal"

msgid "Order total"
msgstr "total fee"

msgid "State/County"
msgstr "Prefectures"

msgid "City"
msgstr "Municipality"

msgid "First line of address"
msgstr "Town name/Character/address"

msgid "Second line of address"
msgstr "building/room number"

...

(* First name = surname, Last name = first name is intentionally written and is not wrong. This is easier for me to use.)

After writing the po file,

$ ./manage.py compilemessages

To create a mo file. The site is now displayed in Japanese.

Tax rate change

The default is a fixed tax rate of 0%. The consumption tax in Japan is 8%, so it needs to be changed.

The tax rate is in partner / strategy.py

$ ./manage.py oscar_fork_app partner oscar_fork

after,

oscar_fork/partner/strategy.py


from decimal import Decimal as D
from oscar.apps.partner import strategy

class Selector(object):
    def strategy(self, request=None, user=None, **kwargs):
        return JPStrategy()

class JP(strategy.FixedRateTax):
    rate = D('0.08')
    exponent = D('1.')

    def pricing_policy(self, product, stockrecord):
        if not stockrecord:
            return prices.Unavailable()
        rate = self.get_rate(product, stockrecord)
        exponent = self.get_exponent(stockrecord)
        tax = (stockrecord.price_excl_tax * rate).quantize(
            exponent, rounding=ROUND_DOWN)
        return prices.TaxInclusiveFixedPrice(
            currency=stockrecord.price_currency,
            excl_tax=stockrecord.price_excl_tax,
            tax=tax)

    def parent_pricing_policy(self, product, children_stock):
        stockrecords = [x[1] for x in children_stock if x[1] is not None]
        if not stockrecords:
            return prices.Unavailable()

        # We take price from first record
        stockrecord = stockrecords[0]
        rate = self.get_rate(product, stockrecord)
        exponent = self.get_exponent(stockrecord)
        tax = (stockrecord.price_excl_tax * rate).quantize(
            exponent, rounding=ROUND_DOWN)

        return prices.FixedPrice(
            currency=stockrecord.price_currency,
            excl_tax=stockrecord.price_excl_tax,
            tax=tax)

class JPStrategy(strategy.UseFirstStockRecord, strategy.StockRequired,
                 JP, strategy.Structured):
    pass

You can write it like this.

class JP(strategy.FixedRateTax):
    rate = D('0.08')

I wrote this. In this case, the amount after the decimal point is treated as it is. For example, in the case of a product of 70 yen excluding tax, it is calculated internally as 75.6 yen including tax. Consider the number after the decimal point.

This was inconvenient for my service, so I changed it as follows

class JP(strategy.FixedRateTax):
    rate = D('0.08')
    exponent = D('1.')

The numbers after the decimal point are rounded off. For products of 70 yen excluding tax, it will be 76 yen including tax.

This time, I wanted to truncate after the decimal point, so I overridden both the pricing_policy and parent_pricing_policy methods and put rounding = ROUND_DOWN in the argument of the quantize method of Decimal.

It's not a bit elegant to override the entire method just because you wanted to truncate it. Is there any good way?

I wonder if it can be realized with decimal.setcontext. I can't do it because it seems to have other effects.

Added to INSTALLED_APPS as usual

settings.py


INSTALLED_APPS += get_core_apps([
    ...
    'oscar_fork.partner',
])

Since you can write branches etc. with logic, you can also write complicated processing. Tariffs etc.

I think that it can be used almost in Japan.

The rest is template creation and translation.

Where is the top page?

By the way. The top page is in promotions. The views are ʻoscar.apps.promotions.views.HomeView, The template is promotions / home.html`. It will take some time to find it, so I will write it down.

Other necessary functions

Payment module

paypal seems to be relatively easy to use with the django-oscar-paypal module. Supports express checkout and payflow. Maybe Express Checkout just gives you a link.

I decided to do it with webpay, so I wrote it myself.

You will be writing by overriding handle_payment in payment.views.PaymentDetailsView.

Recommended Posts

Django Oscar (EC Package) Japan Usage Guide
django oscar simple tutorial