Building your own shop

For simplicity, let’s assume you’re building a new e-commerce project from scratch and have decided to use Oscar. Let’s call this project frobshop

Tip

You can always review the set-up of the Sandbox site in case you have trouble with the below instructions.

Install Oscar and its dependencies

Install Oscar (which will install Django as a dependency), then create the project:

$ mkvirtualenv oscar
$ pip install django-oscar[sorl-thumbnail]
$ django-admin startproject frobshop

If you do not have mkvirtualenv, you can use instead:

$ python3 -m venv oscar
$ . ./oscar/bin/activate
(oscar) $ pip install django-oscar[sorl-thumbnail]
(oscar) $ django-admin startproject frobshop

This will create a folder frobshop for your project. It is highly recommended to install Oscar in a virtualenv.

Tip

sorl-thumbnail is an optional dependency for image thumbnail, but is what Oscar expects to use by default. It can be replaced with easy-thumbnails or a custom thumbnail backend. If you want to use a different backend then remember to change the OSCAR_THUMBNAILER setting to point to it.

Attention

Please ensure that pillow, a fork of the the Python Imaging Library (PIL), gets installed with JPEG support. Supported formats are printed when pillow is first installed. Instructions on how to get JPEG support are highly platform specific, but guides for PIL should work for pillow as well. Generally speaking, you need to ensure that libjpeg-dev is installed and found during installation.

Django settings

First, edit your settings file frobshop/frobshop/settings.py to import all of Oscar’s default settings.

from oscar.defaults import *

Now add Oscar’s context processors to the template settings, listed below:

'oscar.apps.search.context_processors.search_form',
'oscar.apps.checkout.context_processors.checkout',
'oscar.apps.communication.notifications.context_processors.notifications',
'oscar.core.context_processors.metadata',

Next, modify INSTALLED_APPS to be a list, and add django.contrib.sites, django.contrib.flatpages, Oscar’s core apps, and third-party apps that Oscar depends on. Also set SITE_ID:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'django.contrib.sites',
    'django.contrib.flatpages',

    'oscar.config.Shop',
    'oscar.apps.analytics.apps.AnalyticsConfig',
    'oscar.apps.checkout.apps.CheckoutConfig',
    'oscar.apps.address.apps.AddressConfig',
    'oscar.apps.shipping.apps.ShippingConfig',
    'oscar.apps.catalogue.apps.CatalogueConfig',
    'oscar.apps.catalogue.reviews.apps.CatalogueReviewsConfig',
    'oscar.apps.communication.apps.CommunicationConfig',
    'oscar.apps.partner.apps.PartnerConfig',
    'oscar.apps.basket.apps.BasketConfig',
    'oscar.apps.payment.apps.PaymentConfig',
    'oscar.apps.offer.apps.OfferConfig',
    'oscar.apps.order.apps.OrderConfig',
    'oscar.apps.customer.apps.CustomerConfig',
    'oscar.apps.search.apps.SearchConfig',
    'oscar.apps.voucher.apps.VoucherConfig',
    'oscar.apps.wishlists.apps.WishlistsConfig',
    'oscar.apps.dashboard.apps.DashboardConfig',
    'oscar.apps.dashboard.reports.apps.ReportsDashboardConfig',
    'oscar.apps.dashboard.users.apps.UsersDashboardConfig',
    'oscar.apps.dashboard.orders.apps.OrdersDashboardConfig',
    'oscar.apps.dashboard.catalogue.apps.CatalogueDashboardConfig',
    'oscar.apps.dashboard.offers.apps.OffersDashboardConfig',
    'oscar.apps.dashboard.partners.apps.PartnersDashboardConfig',
    'oscar.apps.dashboard.pages.apps.PagesDashboardConfig',
    'oscar.apps.dashboard.ranges.apps.RangesDashboardConfig',
    'oscar.apps.dashboard.reviews.apps.ReviewsDashboardConfig',
    'oscar.apps.dashboard.vouchers.apps.VouchersDashboardConfig',
    'oscar.apps.dashboard.communications.apps.CommunicationsDashboardConfig',
    'oscar.apps.dashboard.shipping.apps.ShippingDashboardConfig',

    # 3rd-party apps that oscar depends on
    'widget_tweaks',
    'haystack',
    'treebeard',
    'sorl.thumbnail',   # Default thumbnail backend, can be replaced
    'django_tables2',
]

SITE_ID = 1

Note that Oscar requires django.contrib.flatpages which isn’t included by default. flatpages also requires django.contrib.sites. More info about installing flatpages is in the Django docs.

Tip

Oscar’s default templates use django-widget-tweaks but it’s optional really. You may decide to use your own templates that don’t use either.

Next, add oscar.apps.basket.middleware.BasketMiddleware and django.contrib.flatpages.middleware.FlatpageFallbackMiddleware to your MIDDLEWARE setting.

MIDDLEWARE = (
    ...
    'oscar.apps.basket.middleware.BasketMiddleware',
    'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware',
)

Set your authentication backends to:

AUTHENTICATION_BACKENDS = (
    'oscar.apps.customer.auth_backends.EmailBackend',
    'django.contrib.auth.backends.ModelBackend',
)

to allow customers to sign in using an email address rather than a username.

Ensure that your media and static files are configured correctly. This means at the least setting MEDIA_URL and STATIC_URL. If you’re serving files locally, you’ll also need to set MEDIA_ROOT and STATIC_ROOT. Check out the sandbox settings for a working example. If you’re serving files from a remote storage (e.g. Amazon S3), you must manually copy a “Image not found” image into MEDIA_ROOT.

Search backend

If you’re happy with basic search for now, you can just add Haystack’s simple backend to the HAYSTACK_CONNECTIONS option in your Django settings:

HAYSTACK_CONNECTIONS = {
    'default': {
        'ENGINE': 'haystack.backends.simple_backend.SimpleEngine',
    },
}

Oscar uses Haystack to abstract away from different search backends. Unfortunately, writing backend-agnostic code is nonetheless hard and Apache Solr is currently the only supported production-grade backend. Your Haystack config could look something like this:

HAYSTACK_CONNECTIONS = {
    'default': {
        'ENGINE': 'haystack.backends.solr_backend.SolrEngine',
        'URL': 'http://127.0.0.1:8983/solr',
        'INCLUDE_SPELLING': True,
    },
}

Oscar includes a sample schema to get started with Solr. More information can be found in the recipe on getting Solr up and running.

Database

Check your database settings. A quick way to get started is to use SQLite:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'db.sqlite3',
        'USER': '',
        'PASSWORD': '',
        'HOST': '',
        'PORT': '',
        'ATOMIC_REQUESTS': True,
    }
}

Note that we recommend using ATOMIC_REQUESTS to tie transactions to requests.

URLs

Alter your frobshop/urls.py to include Oscar’s URLs. You can also include the Django admin for debugging purposes. But please note that Oscar makes no attempts at having that be a workable interface; admin integration exists to ease the life of developers.

If you have more than one language set your Django settings for LANGUAGES, you will also need to include Django’s i18n URLs:

from django.apps import apps
from django.urls import include, path
from django.contrib import admin

urlpatterns = [
    path('i18n/', include('django.conf.urls.i18n')),

    # The Django admin is not officially supported; expect breakage.
    # Nonetheless, it's often useful for debugging.

    path('admin/', admin.site.urls),

    path('', include(apps.get_app_config('oscar').urls[0])),
]

Create database

Oscar ships with migrations. Django’s migration framework will detect them automatically and will do the right thing. Create the database and the shop should be browsable:

$ python manage.py migrate
$ python manage.py runserver

You should now have an empty, but running Oscar install that you can browse at http://localhost:8000.

Initial data

The default checkout process requires a shipping address with a country. Oscar uses a model for countries with flags that indicate which are valid shipping countries and so the country database table must be populated before a customer can check out.

The easiest way to achieve this is to use country data from the pycountry package. Oscar ships with a management command to parse that data:

$ pip install pycountry
[...]
$ python manage.py oscar_populate_countries

By default, this command will mark all countries as a shipping country. Call it with the --no-shipping option to prevent that. You then need to manually mark at least one country as a shipping country.

Creating product classes and fulfilment partners

Every Oscar deployment needs at least one product class and one fulfilment partner. These aren’t created automatically as they’re highly specific to the shop you want to build.

When managing your catalogue you should always use the Oscar dashboard, which provides the necessary functionality. Use your Django superuser email and password to login to: http://127.0.0.1:8000/dashboard/ and create instances of both there.

It is important to note that the Django admin site is not supported. It may or may not work and is only included in the sandbox for developer’s convenience.

For a deployment setup, we recommend creating product classes as data migration.

Defining the order pipeline

The order management in Oscar relies on the order pipeline that defines all the statuses an order can have and the possible transitions for any given status. Statuses in Oscar are not just used for an order but are handled on the line level as well to be able to handle partial shipping of an order.

The order status pipeline is different for every shop which means that changing it is fairly straightforward in Oscar. The pipeline is defined in your settings.py file using the OSCAR_ORDER_STATUS_PIPELINE setting. You also need to specify the initial status for an order and a line item in OSCAR_INITIAL_ORDER_STATUS and OSCAR_INITIAL_LINE_STATUS respectively.

To give you an idea of what an order pipeline might look like take a look at the Oscar sandbox settings:

OSCAR_INITIAL_ORDER_STATUS = 'Pending'
OSCAR_INITIAL_LINE_STATUS = 'Pending'
OSCAR_ORDER_STATUS_PIPELINE = {
    'Pending': ('Being processed', 'Cancelled',),
    'Being processed': ('Processed', 'Cancelled',),
    'Cancelled': (),
}

Defining the order status pipeline is simply a dictionary of where each status is given as a key. Possible transitions into other statuses can be specified as an iterable of status names. An empty iterable defines an end point in the pipeline.

With these three settings defined in your project you’ll be able to see the different statuses in the order management dashboard.

Next steps

The next step is to implement the business logic of your domain on top of Oscar. The fun part.