Build an E-Commerce Store with Django Oscar

Blog / Django · June 7, 2018 · Updated June 10, 2026 · 12 min read
Build an E-Commerce Store with Django Oscar

Build an E-Commerce Store with Django Oscar

How do you build an e-commerce store with Django Oscar? Install django-oscar, add Oscar's app configs to INSTALLED_APPS (after from oscar.defaults import *), set your OSCAR_* options, include Oscar's URLs, then migrate — that gives you a working catalogue, basket, checkout and dashboard out of the box. You then customise it by forking the apps you want to change with python manage.py oscar_fork_app <app> yourproject/, swapping the Oscar entry in INSTALLED_APPS for your fork, and overriding the models, views, URLs or templates you need. That fork-and-override loop is the whole mental model of Oscar.

Django Oscar is an open-source, domain-driven e-commerce framework (not a turnkey store builder) for Django. It is built to be bent to your domain: every model, view and URL is designed to be overridable, which is why it suits complex B2C and B2B commerce that off-the-shelf platforms fight you on. Oscar 3.x runs on modern Django (4.2 LTS and 5.x) and Python 3.10+, so it is a stack you can run in production for years. At MicroPyramid we have built and customised Oscar stores as part of 12+ years and 50+ Django projects, so this guide reflects how we actually set these up today.

Key takeaways

  • Oscar is a framework, not a hosted store. You get catalogue, basket, offers/vouchers, checkout, orders and a dashboard, then customise by forking apps — maximum control, in pure Python/Django.
  • The override pattern is the core skill. oscar_fork_app copies an app into your project; you replace the Oscar entry in INSTALLED_APPS with your fork and extend the abstract models (from oscar.apps.<app>.models import * at the bottom of your models.py).
  • Modern stack. Oscar 3.x supports Django 4.2 LTS / 5.x and Python 3.10+; get_core_apps() was removed in Oscar 2.0 — list the app configs explicitly instead.
  • Build-vs-buy matters. Pick Oscar for control and custom logic, Saleor for a GraphQL/headless core, Shopify for the fastest standard launch, Medusa for a Node-based headless backend.
  • Payments are pluggable. Oscar ships the checkout flow; you bolt on a gateway (PayU, PayPal, Stripe) and can add wallets/store credit with django-oscar-accounts.

What is Django Oscar, and how is it different from a store builder?

Django Oscar is a mature, open-source e-commerce framework that sits on top of Django. Where a hosted platform like Shopify gives you a finished store you configure through an admin, Oscar gives you well-structured commerce building blocks you assemble and override in code. It supports the things real stores need — pluggable tax and shipping calculations, per-customer pricing, multi-currency, ranges, offers and vouchers, and a full staff dashboard.

The defining design decision in Oscar is "override anything". Oscar is split into ~20 self-contained Django apps (catalogue, basket, checkout, order, partner, offer, voucher, dashboard, and so on). Almost every model is an abstract base, and views, URLs and templates are all designed to be replaced. To change behaviour you don't patch Oscar's source — you fork the relevant app into your own project and override just the pieces you care about, leaving the rest inherited from core. This is what makes Oscar a good fit for unusual catalogues, B2B rules, and bespoke checkouts, and it is also the part newcomers most often get stuck on (covered below).

Because it is self-hosted and open-source, there are no per-transaction platform fees or app-store rate limits — you own the data model, the checkout and the roadmap. The trade-off is that you (or a partner) own hosting, upgrades and maintenance.

When should you choose Oscar? (Oscar vs Saleor vs Shopify vs Medusa)

Start with the decision, not the framework. If you sell a handful of standard products and want to launch this week, a hosted platform will be faster. Reach for Oscar when you need to own the commerce logic: complex or per-customer pricing, B2B quoting and approvals, deep ERP/CRM integration, a large or unusual catalogue, or a checkout that platform "apps" can't express cleanly — and you want it all in Python/Django.

Here is how the common options compare. (Hosted platforms typically charge monthly and/or per-transaction fees; Oscar, Saleor and Medusa are open-source and self-hosted, so you trade subscription fees for engineering and hosting ownership.)

Factor Django Oscar Saleor Shopify (hosted) Medusa
Type Django framework, fork-and-override GraphQL, headless platform Hosted SaaS store Node.js headless backend
Language / stack Python / Django Python / Django core, GraphQL API Proprietary (Liquid, apps) JavaScript / Node
Control over models & logic Full (override any class) High (API-first, own front end) Limited (platform schema) High (modular, own front end)
Front end Server-rendered templates (or headless via DRF) Bring your own (Next.js etc.) Themes / Hydrogen Bring your own (Next.js etc.)
Time to first launch Moderate Moderate Fastest Moderate
Cost model Open-source, self-hosted (no platform fees) Open-source or Saleor Cloud Monthly plan + per-transaction + paid apps Open-source, self-hosted
Best fit Complex B2C/B2B in a Django shop API-first teams wanting a Python core Standard catalogues, fastest launch JS teams wanting a headless backend

A simple rule of thumb: choose Oscar if your team already lives in Django and you want commerce primitives you can override class-by-class; Saleor if you want a GraphQL, headless-first core; Shopify if standardness and speed beat control; Medusa if your team is Node-first and wants a headless backend.

How do you install and bootstrap Django Oscar?

The canonical setup is: install the package, create a project, register Oscar's apps and settings, include its URLs, then migrate. Do this once and you have a fully working store you can log into and start customising.

# Oscar 3.x supports Django 4.2 LTS / 5.x and Python 3.10+.
# Work in a virtualenv.
python -m pip install django-oscar

# Create your project (use a folder name you control, e.g. "myshop")
django-admin startproject myshop .

Configure settings.py

The most important line is from oscar.defaults import *, which loads Oscar's many OSCAR_* defaults so you only override what you need. Then list Oscar's app configs in INSTALLED_APPS, add the third-party apps Oscar depends on, set SITE_ID, and add Oscar's context processors and the basket middleware.

Note a common stumbling block from older tutorials: get_core_apps() was removed in Oscar 2.0. Modern Oscar (2.x/3.x) lists each app config explicitly, and you override an app later by swapping its entry here for your fork.

# myshop/settings.py
from oscar.defaults import *  # noqa: load all OSCAR_* defaults

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 core apps (override later by replacing the line with your fork)
    '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 Oscar depends on
    'widget_tweaks',
    'haystack',
    'treebeard',
    'sorl.thumbnail',
    'django_tables2',
]

SITE_ID = 1

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware',
    'oscar.apps.basket.middleware.BasketMiddleware',
]

# Add Oscar's context processors to your TEMPLATES['OPTIONS']['context_processors']:
#   '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',

# A few common OSCAR_* overrides (everything else comes from oscar.defaults):
OSCAR_SHOP_NAME = 'My Store'
OSCAR_DEFAULT_CURRENCY = 'USD'
OSCAR_ALLOW_ANON_CHECKOUT = True

# Haystack search backend (use Elasticsearch/Solr in production)
HAYSTACK_CONNECTIONS = {
    'default': {
        'ENGINE': 'haystack.backends.simple_backend.SimpleEngine',
    },
}

Wire up URLs, then migrate

Oscar exposes one root app config whose URLs you include at the path you want the store to live at. In modern Oscar you fetch it from Django's app registry, which also makes it easy to swap in a custom root config later.

# myshop/urls.py
from django.apps import apps
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('admin/', admin.site.urls),
    path('i18n/', include('django.conf.urls.i18n')),
    # Mount the whole Oscar shop at the site root
    path('', include(apps.get_app_config('oscar').urls[0])),
]
# Create the schema (Oscar ships all its migrations), an admin user, and run.
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver

# Storefront:  http://127.0.0.1:8000/
# Dashboard:   http://127.0.0.1:8000/dashboard/
# Load the demo catalogue fixtures if you want sample data, then
# add products and partners (stockrecords) from the dashboard.

How do you override an Oscar app? (the part people get stuck on)

This is the single most important thing to understand about Oscar: you customise it by forking apps, not by editing Oscar's source. The workflow is always the same three moves — fork the app, point INSTALLED_APPS at your fork, then override only what you need.

The oscar_fork_app management command does the mechanical part. It copies the app into your project with the right apps.py, admin.py, models.py and migrations folder so your fork is a proper local app you can extend.

# Fork the catalogue app into your project package (e.g. into ./myshop/)
python manage.py oscar_fork_app catalogue myshop/

# This creates myshop/catalogue/ with apps.py, admin.py, models.py,
# and a migrations/ folder, ready for you to customise.

Override a model

Oscar's models are abstract base classes, so to add fields you subclass the Abstract* model and then re-import the rest of Oscar's models for that app at the bottom of the file — this is the step people forget, and skipping it means the app's other models silently disappear.

# myshop/catalogue/models.py
from django.db import models
from oscar.apps.catalogue.abstract_models import AbstractProduct


class Product(AbstractProduct):
    """Custom product with extra, domain-specific fields."""
    video_url = models.URLField(blank=True, null=True)
    brand = models.CharField(max_length=255, blank=True)
    warranty_months = models.PositiveIntegerField(default=0)

    def get_brand_display(self):
        return self.brand or 'Generic'


# IMPORTANT: re-import the remaining catalogue models so they are still
# registered. Without this line, Category, ProductClass, etc. vanish.
from oscar.apps.catalogue.models import *  # noqa
# 1) Point INSTALLED_APPS at your fork instead of Oscar's app.
#    Replace:  'oscar.apps.catalogue.apps.CatalogueConfig',
#    With:     'myshop.catalogue.apps.CatalogueConfig',

# 2) Generate and apply migrations for your now-concrete models.
python manage.py makemigrations catalogue
python manage.py migrate

Override views, URLs and templates

The same fork lets you override behaviour beyond models:

  • Views — subclass the Oscar view in your fork's views.py and tell the app config to use it.
  • URLs — override get_urls() on your app config to add or change routes (e.g. rename /catalogue/ to /catalog/), then call self.post_process_urls(urls).
  • Templates — put a template at the same relative path inside your own templates directory (listed before Oscar's in TEMPLATES['DIRS']) to replace it, or use {% extends 'oscar/.../whatever.html' %} and override just the blocks you want.

For a full, worked walkthrough of these overrides, see our guide on customising Oscar models, views and URLs.

# myshop/offer/apps.py - add a custom view + URL by extending the app config
from django.urls import path
from oscar.apps.offer.apps import OfferConfig as CoreOfferConfig


class OfferConfig(CoreOfferConfig):
    def ready(self):
        super().ready()
        from .views import MyExtraView
        self.extra_view = MyExtraView

    def get_urls(self):
        urls = super().get_urls()
        urls += [
            path('extra/', self.extra_view.as_view(), name='extra'),
        ]
        return self.post_process_urls(urls)

How do payments and checkout work in Oscar?

Oscar ships a complete, multi-step checkout flow (shipping address → shipping method → payment → preview → place order) as a set of overridable views. What Oscar deliberately does not do is talk to a specific payment provider — that is left to you, because gateways differ by country and business. You integrate a gateway by overriding the checkout's payment step to authorise/capture the charge and record it against the order.

To understand the moving parts before you customise them, read our deep-dive on Oscar's checkout flow. Then wire in a gateway — we have step-by-step guides for PayU payment gateway integration and PayPal integration with Django; the same pattern applies to Stripe and most other processors. The golden rule holds everywhere: card data should go from the browser straight to the gateway (hosted/tokenised flow), and your backend should treat the gateway's confirmation, not the browser redirect, as the source of truth for "paid".

For wallets, store credit, gift cards or loyalty balances, add django-oscar-accounts, the companion package that gives Oscar a double-entry accounts/ledger system you can debit and credit during checkout.

Where MicroPyramid fits

Oscar rewards teams who want full control, but the fork-and-override model, the payment integrations and the upgrade path all take real Django experience to get right. We have built, customised and maintained Django e-commerce — including Oscar stores, headless storefronts and Saleor builds — across 12+ years and 50+ projects, and we increasingly embed AI (search relevance, recommendations, support agents) so stores do more with less. If you are weighing Oscar against a hosted platform or need help shipping a custom store, our Django development team can help you make the call and build it.

Frequently Asked Questions

What is Django Oscar used for?

Django Oscar is an open-source, domain-driven e-commerce framework for building custom online stores on Django. It is used for everything from large-scale B2C catalogues to complex B2B applications with bespoke pricing, quoting and fulfilment rules. Unlike a hosted store builder, Oscar gives you overridable commerce building blocks — catalogue, basket, offers, checkout, orders and a staff dashboard — that you assemble and customise in Python, so it suits stores whose logic doesn't fit a cookie-cutter platform.

Is Django Oscar still maintained and what versions does it support?

Yes. Oscar is actively maintained as an open-source project. The current 3.x line supports modern Django (4.2 LTS and 5.x) and Python 3.10+, so you can run a supported, secure stack in production for years. Note that the API has evolved: get_core_apps() was removed in Oscar 2.0, so older tutorials using it are out of date — modern setups list each Oscar app config explicitly in INSTALLED_APPS and load defaults with from oscar.defaults import *.

How do you customise models and views in Django Oscar?

You fork the relevant app and override only what you need. Run python manage.py oscar_fork_app <app> yourproject/ to copy the app into your project, then replace that app's entry in INSTALLED_APPS with your fork's config. To change a model, subclass the Abstract* base class and re-import the rest of the app's models at the bottom of your models.py (from oscar.apps.<app>.models import *), then run makemigrations and migrate. Views and URLs are overridden through the app config; templates by shadowing Oscar's paths or extending its blocks.

Django Oscar vs Saleor vs Shopify — which should I choose?

Choose Oscar if your team works in Django and you want commerce primitives you can override class-by-class with full control and no platform fees. Choose Saleor if you want a GraphQL, headless-first core with your own decoupled storefront. Choose Shopify if you have a fairly standard catalogue and want the fastest launch and least maintenance, accepting monthly and per-transaction fees plus an app ecosystem. Medusa is the pick for Node-first teams wanting a headless backend. The trade-off is always control and ownership (Oscar/Saleor/Medusa) versus speed and managed convenience (Shopify).

How do you add payments to a Django Oscar store?

Oscar provides the full checkout flow but no built-in gateway, so you override the checkout payment step to authorise and capture the charge with your chosen processor, then record a payment source/event against the order. Use a hosted or tokenised flow so card data goes from the browser directly to the gateway, and treat the gateway's server-side confirmation (not the browser redirect) as the source of truth. We have walkthroughs for PayU and PayPal; Stripe and most processors follow the same pattern. For wallets and store credit, add the django-oscar-accounts package.

Do I need to know Django to use Oscar?

Yes — Oscar is a developer framework, not a no-code store builder. You should be comfortable with Django models, class-based views, URLs, templates and migrations, because customisation happens in code through the fork-and-override pattern. That requirement is also Oscar's strength: it means there is no ceiling on what you can build. If you want the control of Oscar without staffing the Django expertise in-house, this is exactly the kind of build our team takes on.

Share this article