Добавление собственного приложения в dashboard в django-oscar

В документации не описан процесс добавления приложения непосредственно в dashboard, поэтому подробности ниже.

Инструкция ниже подходит как для перегрузки (overriding) приложений из oscar, так и для добавления собственных приложений.

Если нужно сделать форк

1. Делаем форк приложения в папку приложений своего проекта, допустим в apps. Эта папка должна быть модулем, т.е. в ней должен быть файл __init__.py (скорее всего пустой):
./manage.py oscar_fork_app dashboard.catalogue apps/
Эта команда создаст папку catalogue с файлами:
# apps/dashboard/catalogue/__init__.py

default_app_config = 'apps.dashboard.catalogue.config.CatalogueDashboardConfig'
и
# apps/dashboard/catalogue/config.py

from oscar.apps.dashboard.catalogue import config


class CatalogueDashboardConfig(config.CatalogueDashboardConfig):
    name = 'apps.dashboard.catalogue'

2. Допустим, нашей целью является переписать ProductListView. Для этого создаем в этой папке файл views.py с таким содержимым:
# apps/dashboard/catalogue/views.py

from oscar.apps.dashboard.catalogue.views import ProductListView as CoreProductListView
from apps.catalogue.models import Product  # либо импортируйте
                                           # из oscar

class ProductListView(CoreProductListView):
    def get_queryset(self):
        queryset = ...
        return queryset

3. Добавляем наше приложение в settings.py
# settings.py

from oscar import get_core_apps
# ...
INSTALLED_APPS = [
    # all your non-Oscar apps
] + get_core_apps([
    # your Oscar apps
    'apps.dashboard.catalogue',
])

Все остальное oscar подхватит сам. На этом можно закончить. Но если вы решили добавить собственное приложение в меню dashboard, то нужно сделать еще кое-что.

Если надо добавить собственное приложение в dashboard

Допустим, мы создали приложение News, которое публикует новости на сайте. Конечно, можно добавить его в родную админку Django, но это при условии, что она включена, т.к. она не нужна для работы django-oscar. Ну, почти не нужна :)

1. Создаем папку apps/dashboard/news с файлами, как и в случае с форком:
# apps/dashboard/news/__init__.py

default_app_config = (
    'apps.dashboard.news.config.NewsDashboardConfig')
# apps/dashboard/news/config.py

from django.apps import AppConfig
from django.utils.translation import ugettext_lazy as _


class NewsDashboardConfig(AppConfig):
    label = 'news_dashboard'
    name = 'apps.dashboard.news'
    verbose_name = _('News')

2. Создаем файл app.py:
# apps/dashboard/news/app.py

from django.conf.urls import url
from oscar.core.application import Application
from oscar.core.loading import get_class


class NewsDashboardApplication(Application):
    name = None
    default_permissions = ['is_staff', ]
    permissions_map = _map = {
        'news-list': (['is_staff'], ['partner.dashboard_access']),
        'news-update': (['is_staff'], ['partner.dashboard_access']),
    }

    news_list_view = get_class('apps.dashboard.news.views',
                               'NewsListView')
    news_create_view = get_class('apps.dashboard.news.views',
                                 'NewsCreateView')
    news_update_view = get_class('apps.dashboard.news.views',
                                 'NewsUpdateView')
    news_delete_view = get_class('apps.dashboard.news.views',
                                 'NewsDeleteView')

    def get_urls(self):
        urls = [
            url(r'^$',
                self.news_list_view.as_view(),
                name='news-list'),
            url(r'^add/$',
                self.news_create_view.as_view(),
                name='news-create'),
            url(r'^(?P\d+)/update/$',
                self.news_update_view.as_view(),
                name='news-update'),
            url(r'^(?P\d+)/delete/$',
                self.news_delete_view.as_view(),
                name='news-delete'),
        ]
        return self.post_process_urls(urls)

application = NewsDashboardApplication()

3. Редактируем settings.py:
# settings.py

INSTALLED_APPS = [
    # your non-Oscar apps
    'news',
    'apps.dashboard.news',
] + get_core_apps([
    # your Oscar apps
])

OSCAR_DASHBOARD_NAVIGATION += [
    {
        'label': 'Прочие',
        'icon': 'icon-gift',
        'children': [
            {
                'label': 'Новости',
                'url_name': 'dashboard:news-list',
            }
        ]
    }
]
В принципе этого уже достаточно, чтобы в меню dashboard появился новый пункт Прочие и в нем подпункт Новости. Очевидно, для полноценной работы нужно будет создать views.py и описать в нем обычные class-based views, указанные в app.py

Обратите внимание также, что родные приложения oscar используют в dashboard библиотеку django-tables2 для представления листингов. Например, в нашем случае NewsListView и таблица NewsTable выглядят так:
# apps/dashboard/news/views.py

from django.views import generic
from django_tables2 import SingleTableMixin
from news.models import News
from apps.dashboard.news.tables import NewsTable


class NewsListView(SingleTableMixin, generic.TemplateView):
    template_name = 'dashboard/news/news_list.html'
    table_class = NewsTable
    context_table_name = 'news'
    table_data = News.objects.all()
# apps/dashboard/news/tables.py

from django_tables2 import Table, TemplateColumn
from django.utils.translation import ugettext_lazy as _
from oscar.core.loading import get_class
from news.models import News

DashboardTable = get_class('dashboard.tables', 'DashboardTable')


class NewsTable(Table):
    # По желанию переписываем отображение любого поля
    body = TemplateColumn(template_code='{{ record.body|striptags|truncatechars:50 }}')

    # Добавляем столбец с действиями
    actions = TemplateColumn(
        verbose_name=_('Actions'),
        template_name='dashboard/news/news_row_actions.html',
        orderable=False)

    class Meta(DashboardTable.Meta):
        model = News

Почти закончили! Осталось написать шаблоны для views и для таблицы (если импользуете news_row_actions.html). Они абсолютно стандартные и при этом занимают много места, поэтому я не буду приводить их здесь.

Если все же возникнут затруднения, смотрите исходники django-oscar и сделайте шаблоны по аналогии.

И, конечно, по любым непонятным моментам задавайте вопросы в комментариях, я распишу более подробно.