Creating a Django-Oscar App with Dashboard (Part 1)

Farid Musa
Level Up Coding
Published in
6 min readMar 16, 2021

--

In this tutorial, you are going to learn how to create a new Django app and integrate it into Oscar e-commerce framework. Particularly, we will create a new sample Django app called boutique and integrate it to Oscar's default front and dashboard.

Getting ready (django-oscar)

First, it is necessary to create a virtual environment to work in. I use pipenv as a virtual environment for its simplicity and ease of use. Create a directory called /myoscarapp, move inside and run the following command:

$ pipenv shell

Then install the django-oscar using pip:

$ pip install django-oscar[sorl-thumbnail]

Now create a brand new Dango project using the following command and rename the created directory to src for convenience:

$ django-admin startproject myoscarproject
$ mv myoscarproject src

Next, configure Django settings.py and urls.py as described in Oscar's corresponding documentation. Run makemigrations and migrate:

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

Test the website:

python manage.py runserver

The following screen should be now available:

Creating “boutique” app for Django-Oscar

The new app is created as usual using the following command:

python manage.py startapp boutique

Once again as usual after the app is created, it is necessary to register the app in INSTALLED_APPS in settings.py as shown below:

INSTALLED_APPS = [
...
'boutique.apps.BoutiqueConfig',
]

Similarly, your urls.py should look like this:

from django.apps import apps
from django.urls import include, path
from django.contrib import admin
urlpatterns = [
path('i18n/', include('django.conf.urls.i18n')),
path('admin/', admin.site.urls),
#path('dashboard/boutique/', apps.get_app_config('boutique_dashboard').urls),
path('boutique/', apps.get_app_config('boutique').urls),
path('', include(apps.get_app_config('oscar').urls[0])),
]

In the code above, line with boutique_dashboard URL configuration is temporarily commented out and will be turned on when Oscar's dashboard app is forked.

Models for “boutique” app

Create the following model that will represent a single boutique with three fields.

from django.db import modelsclass Boutique(models.Model):
name = models.CharField(max_length=255, blank=True, null=True)
manager = models.CharField(max_length=150, blank=True, null=True)
city = models.CharField(max_length=150, blank=True, null=True)
class Meta:
app_label = 'boutique'

App configs for “boutique” app

While usual Django app’s config class in apps.py inherits Django's default django.apps.AppConfigclass, Oscar app's must inherit oscar.core.application.OscarConfig instead. Your apps.py should look like this:

from oscar.core.application import OscarConfig
from django.urls import path, re_path
from oscar.core.loading import get_class
class BoutiqueConfig(OscarConfig):
name = 'boutique'
namespace = 'boutique'
def ready(self):
super().ready()
self.boutique_list_view = get_class(
'boutique.views', 'BoutiqueListView')
self.boutique_detail_view = get_class(
'boutique.views', 'BoutiqueDetailView')
def get_urls(self):
urls = super().get_urls()
urls += [
path('', self.boutique_list_view.as_view(), name='index'),
re_path(r'^view/(?P<pk>\d+)/$',
self.boutique_detail_view.as_view(), name='details'),
]
return self.post_process_urls(urls)

It is optional to use get_class and get_model when developing your own app but required when overriding Oscar apps. However, I prefer using Oscar's approach in all cases as I previously encountered various errors when importing modules using import statement.

Admin for “boutique” app

This step is optional and Oscar’s dashboard is sufficient to add, modify and remove Boutique elements to the database. However, for early testing let's register our model in Django's admin. Add the following code to the admin.py in the app's directory.

from django.contrib import admin
from oscar.core.loading import get_model
Boutique = get_model('boutique', 'Boutique')class BoutiqueAdmin(admin.ModelAdmin):
pass
admin.site.register(Boutique, BoutiqueAdmin)

Now that the model is registered in Django’s admin, go on and add few items for testing.

To access Django’s admin you will need to create a super user using command python manage.py createsuperuser

Views for “boutique” app

There is nothing special in the implementation of views that will deliver context to the front pages. Following is a working views.py based on Django's generic class-based views.

from django.views import generic
from oscar.core.loading import get_model
Boutique = get_model('boutique', 'Boutique')class BoutiqueListView(generic.ListView):
model = Boutique
template_name = 'boutique/boutique_list.html'
context_object_name = 'boutique_list'
class BoutiqueDetailView(generic.DetailView):
model = Boutique
template_name = 'boutique/boutique_details.html'
context_object_name = 'boutique'

Front-end templates for “boutique” views

First and foremost, let’s override Oscar’s navigation template by adding a URL to our BoutiqueListView. First, create a directory called oscar in in /src/templates directory. Any template file with the same relative path Oscar's templates from source code will be overridden by Oscar and become a higher priority template. Because Oscar is developed in a very smart and customizable way, it is very easy to add an element to the original Oscar template navigation. The original template HTML file from Oscar's source code can be found in /templates/oscar/partials/nav_primary.html. Accordingly, we need to create a file oscar/partials/nav_primary.html that will contain the following code:

{% extends "oscar/partials/nav_primary.html" %}
{% load i18n %}
{% block nav_items %}
{{ block.super }}
<li class="nav-item dropdown">
<a class="nav-link" href="#" role="button">
{% trans "Boutiques" %}
</a>
</li>
{% endblock %}

In the code above, we first extend the original Oscar’s template. Then we override the block nav_items by adding new elements to Oscar's default front-end navigation. After restarting the server, the following front should show up:

Template for list of boutiques

Previously we created a view BoutiqueListView, which is responsible for delivering the context with a list of Boutique instances to the template boutique/boutique_list.html. Therefore, we first create an HTML file /src/templates/boutique/boutique_list.html. Notice that this template file is not placed under /src/templates/oscar the directory. This is because we do not override Oscar's template and merely creating a new custom template. However, in our case, it does extend the default Oscar layout template as shown:

{% extends "oscar/layout.html" %}{% load i18n %}
{% load product_tags %}
{% block title %}
{% trans "Boutiques" %} | {{ block.super }}
{% endblock %}
{% block breadcrumbs %}
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="{{ homepage_url }}">{% trans "Home" %}</a>
</li>
<li class="breadcrumb-item active" aria-current="page">{% trans "Boutiques" %}</li>
</ol>
</nav>
{% endblock %}
{% block headertext %}
{% trans "Boutique" %}
{% endblock %}
{% block content %}
{% if not boutique_list %}
<p>{% trans "There are no boutique at the moment." %}</p>
{% else %}
{% for boutique in boutique_list %}
<p>
<h2><a href="{% url 'boutique:details' boutique.pk %}">{{ boutique.name }}</a></h2>
The boutique is in: {{ boutique.city }}
</p> <hr/>
{% endfor %}
{% endif %}
{% endblock content %}

The result should look like this:

Template for boutique details

Now that we have a page with a list of our boutique elements let’s add a page where users can view details of any given boutique. Similarly to the listing template, let’s create a new HTML file /src/templates/boutique/boutique_details.html with the following code:

{% extends "oscar/layout.html" %}{% load i18n %}
{% load product_tags %}
{% block title %}
{% trans "Boutiques" %} | {{ block.super }}
{% endblock %}
{% block breadcrumbs %}
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="{{ homepage_url }}">{% trans "Home" %}</a>
</li>
<li class="breadcrumb-item" aria-current="page">
<a href="{% url 'boutique:index' %}">{% trans "Boutiques" %}</a>
</li>
<li class="breadcrumb-item active" aria-current="page">{{ boutique.name }}</li>
</ol>
</nav>
{% endblock %}
{% block headertext %}
{% trans "Boutique" %}
{% endblock %}
{% block content %}
<p>
<h2>{{ boutique.name }}</h2> <br>
The boutique is in: {{ boutique.city }} <br>
The boutique's manager is Mr/Mrs: <strong>{{ boutique.manager }} </strong>
</p>
{% endblock content %}

The result should look like this:

At this point the app’s model, configs, and front-end templates are ready. In the next tutorial, we will develop an Oscar dashboard for the boutique app.

Originally published at https://mmtechslv.com on March 16, 2021.

--

--