Adding a custom app to the dashboard

1,383 views
Skip to first unread message

Paul Walsh

unread,
Apr 20, 2014, 8:34:50 AM4/20/14
to django...@googlegroups.com
It seems that whatever I try, I can't get anything custom to appear in the dashboard.

After trying various combinations of what I find at the following links:





I'm still no closer to getting anything there at all.

Here is my setting:

OSCAR_DASHBOARD_NAVIGATION += [
    {
        'label': 'Staff Picks',
        'children': [
            {
                'label': 'Picks',
                'url_name': 'staffpick-dashboard:list',
            },
        ]
    },
]

and I have tried putting my dashboard in in each of these locations:





I can *remove* existing apps from the dashboard, for example by changing my add and assignment operator to an assignment operator, like so:

OSCAR_DASHBOARD_NAVIGATION = [
    {
        'label': 'Staff Picks',
        'children': [
            {
                'label': 'Pickles',
                'url_name': 'staffpick-dashboard:list',
            },
        ]
    },
]


I need a foolproof way to make this work, as I'm quite lost with it at present.

Izidor Matušov

unread,
Apr 22, 2014, 4:45:47 AM4/22/14
to django...@googlegroups.com
Hi Paul,

do you include URL for staffpick-dashboard:list in urlpatterns? You can
find out by running

./manage.py show_urls

If url_name can't be reversed, the item is not shown in navigation.

Izi

On 20/04/14 13:34, Paul Walsh wrote:
> It seems that whatever I try, I can't get anything custom to appear in the
> dashboard.
>
> After trying various combinations of what I find at the following links:
>
> http://django-oscar.readthedocs.org/en/latest/howto/how_to_configure_the_dashboard_navigation.html
>
> http://django-oscar.readthedocs.org/en/latest/ref/apps/dashboard.html
>
> https://groups.google.com/forum/#!topic/django-oscar/D96E15xcjPk
>
>
> I'm still no closer to getting anything there at all.
>
> Here is my setting:
>
> OSCAR_DASHBOARD_NAVIGATION *+=* [
> {
> 'label': 'Staff Picks',
> 'children': [
> {
> 'label': 'Picks',
> 'url_name': 'staffpick-dashboard:list',
> },
> ]
> },
> ]
>
> and I have tried putting my dashboard in in each of these locations:
>
> project.apps.staffpicks.dashboard.app
>
> project.apps.dashboard.staffpicks.app
>
>
>
> I can *remove* existing apps from the dashboard, for example by changing my
> add and assignment operator to an assignment operator, like so:
>
> OSCAR_DASHBOARD_NAVIGATION *=* [
> {

Paul Walsh

unread,
Apr 22, 2014, 4:51:27 AM4/22/14
to django...@googlegroups.com
Hi,

I have no show_urls management command. I’m working on a branch of master at the moment.

But, my StaffPick dashboard app looks like this:

# import other stuff
from oscar.core.application import Application

class StaffPicksDashboardApplication(Application):

    name = 'staffpick-dashboard'

    staffpick_list_view = views.StaffPickListView

    def get_urls(self):
        urlpatterns = patterns('',
            url(
                r'^$',
                self.staffpick_list_view.as_view(),
                name='list'
            ),
        )
        return self.post_process_urls(urlpatterns)

    def get_url_decorator(self, url_name):
        return staff_member_required


application = StaffPicksDashboardApplication()


-- 
https://github.com/tangentlabs/django-oscar
http://django-oscar.readthedocs.org/en/latest/
https://twitter.com/django_oscar
--- 
You received this message because you are subscribed to a topic in the Google Groups "django-oscar" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/django-oscar/tfAkJFARTGM/unsubscribe.
To unsubscribe from this group and all its topics, send an email to django-oscar...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-oscar.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-oscar/53562C3B.2060206%40tangentsnowball.com.
For more options, visit https://groups.google.com/d/optout.

Izidor Matušov

unread,
Apr 22, 2014, 9:11:04 AM4/22/14
to django...@googlegroups.com
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 22/04/14 09:51, Paul Walsh wrote:
> Hi,
>
> I have no show_urls management command. I’m working on a branch of
> master at the moment.

show_urls [0] comes from django-extensions, very handy module.

0:
http://django-extensions.readthedocs.org/en/latest/command_extensions.html?highlight=show_urls

>
> But, my StaffPick dashboard app looks like this:
>

You need to include StaffPick somewhere. Either override dashboard app
and add your URL there, or alternatively add application.urls directly
to your urlpatterns of your project.

Izi
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQEcBAEBAgAGBQJTVmpoAAoJEDkdYnif+pGn+fQIALJVlsdlipdgPngSRpLXi1nL
AmPba7cXF/SGqcL5Bqi9Uh7a2sTRZPhjvNHhvfdewItyVjqG5SRQ5lc+tJSpybP2
mrRGk3ZiwjlZiRelGqIAwG/An8k8C4H0T04gXqsOdIqWr8/ntwITt6eFFYFgIMA3
sKl9d/NM4ch481xZ2+bvc+xVtknPAtQmtaVwioR1ISAiAHthW4DYlFzf1JU0Ka/h
C250elduOzpoC9yMsOYG7VMAkxMwQVuPsVtf4i6RjL6KsZ9+T7VDvdWECNYTPaq7
huSpUrpghUJZ6CaWINHgtDRfhk6bCWQ9UqY2L/PhdAdn/OwwoAh6hr7IgCrQNwg=
=860L
-----END PGP SIGNATURE-----

Paul Walsh

unread,
Apr 22, 2014, 12:12:36 PM4/22/14
to django...@googlegroups.com
Oh sure, I’m doing that of course, but it still doesn’t work.


Here is everything I have in my code related to dashboard:

#### settings
INSTALLED_APPS = [
# stuff
'hamigdalor.apps.dashboard',
'hamigdalor.apps.staffpicks’,
# stuff
] + get_core_apps()

OSCAR_DASHBOARD_NAVIGATION += [
{
'label': 'Staff Picks',
'children': [
{
'label': 'Staff Picks',
'url_name': 'staffpick-dashboard:list',
},
]
},
]

#### hamigdalor.apps.staffpicks.dashboard.app
# stuff removed
from oscar.core.application import Application
from . import views


class StoresDashboardApplication(Application):

name = 'staffpick-dashboard'

staffpick_list_view = views.StaffPickListView

def get_urls(self):
urlpatterns = patterns('',
url(
r'^$',
self.staffpick_list_view.as_view(),
name='list'
),
)
return self.post_process_urls(urlpatterns)

def get_url_decorator(self, url_name):
return staff_member_required


application = StoresDashboardApplication()


#### hamigdalor.apps.dashboard.app
# stuff removed
from oscar.apps.dashboard.app import DashboardApplication
from hamigdalor.apps.staffpicks.dashboard.app import application as staffpicks_dashboard


class HaMigdalorDashboardApplication(DashboardApplication):

staffpicks_app = staffpicks_dashboard

def get_urls(self):
urls = [
url(r'^$', self.index_view.as_view(), name='index'),
url(r'^catalogue/', include(self.catalogue_app.urls)),
url(r'^reports/', include(self.reports_app.urls)),
url(r'^orders/', include(self.orders_app.urls)),
url(r'^users/', include(self.users_app.urls)),
url(r'^content-blocks/', include(self.promotions_app.urls)),
url(r'^pages/', include(self.pages_app.urls)),
url(r'^partners/', include(self.partners_app.urls)),
url(r'^offers/', include(self.offers_app.urls)),
url(r'^ranges/', include(self.ranges_app.urls)),
url(r'^reviews/', include(self.reviews_app.urls)),
url(r'^vouchers/', include(self.vouchers_app.urls)),
url(r'^comms/', include(self.comms_app.urls)),
url(r'^staffpicks/', include(self.staffpicks_app.urls)),
]
return self.post_process_urls(patterns('', *urls))


application = HaMigdalorDashboardApplication()


#### hamigdalor.app
from oscar.core.loading import get_class
from oscar.app import Shop


class HaMigdalorShop(Shop):

search_app = get_class('hamigdalor.apps.search.app', 'application')
dashboard_app = get_class('hamigdalor.apps.dashboard.app', 'application')


application = HaMigdalorShop()


####hamigdalor.urls
from django.conf.urls import patterns, include, url
from django.conf.urls.static import static
from django.contrib import admin
from django.conf import settings
from hamigdalor.app import application
from hamigdalor.apps.contributors.app import application as contributors
from hamigdalor.apps.events.app import application as events
from hamigdalor.apps.interviews.app import application as interviews
from hamigdalor.apps.newsletters.app import application as newsletters
from hamigdalor.apps.quotations.app import application as quotations
from hamigdalor.apps.staffpicks.app import application as staffpicks
from hamigdalor.apps.tags.app import application as tags
from hamigdalor.apps.windows.app import application as windows


admin.autodiscover()


urlpatterns = patterns('',
url(r'^contributors/', include(contributors.urls)),
url(r'^events/', include(events.urls)),
url(r'^interviews/', include(interviews.urls)),
url(r'^newsletters/', include(newsletters.urls)),
url(r'^quotations/', include(quotations.urls)),
url(r'^staffpicks/', include(staffpicks.urls)),
url(r'^tags/', include(tags.urls)),
url(r'^window/', include(windows.urls)),
url(r'^admin/', include(admin.site.urls)),
url(r'', include(application.urls)),
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)




I’ve now just discovered that if I add the dashboard URLs to my main urls file (as you suggest), then I can get the added menu in the dashboard (e.g.: url(r’^staffpicks-dashboard/', include(staffpicks_dashboard.urls)),). But, why do I need to do that when I am already overriding the dashboard app and including it there?
> --
> https://github.com/tangentlabs/django-oscar
> http://django-oscar.readthedocs.org/en/latest/
> https://twitter.com/django_oscar
> ---
> You received this message because you are subscribed to a topic in the Google Groups "django-oscar" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/topic/django-oscar/tfAkJFARTGM/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to django-oscar...@googlegroups.com.
> Visit this group at http://groups.google.com/group/django-oscar.
> To view this discussion on the web visit https://groups.google.com/d/msgid/django-oscar/53566A68.9040401%40tangentsnowball.com.

Izidor Matušov

unread,
Apr 23, 2014, 5:00:13 AM4/23/14
to django...@googlegroups.com
On 22/04/14 17:12, Paul Walsh wrote:
>
> I've now just discovered that if I add the dashboard URLs to my main
urls file (as you suggest), then I can get the added menu in the
dashboard (e.g.: url(r'^staffpicks-dashboard/',
include(staffpicks_dashboard.urls)),). But, why do I need to do that
when I am already overriding the dashboard app and including it there?

Does it fix your original problem then?


> #### settings
> INSTALLED_APPS = [
> # stuff
> 'hamigdalor.apps.dashboard',
> 'hamigdalor.apps.staffpicks',
> # stuff
> ] + get_core_apps()

try to put dashboard app as overriden:

> INSTALLED_APPS = [
> # stuff
> 'hamigdalor.apps.staffpicks',
> # stuff
> ] + get_core_apps(['hamigdalor.apps.dashboard',])

Paul Walsh

unread,
Apr 23, 2014, 5:11:41 AM4/23/14
to django...@googlegroups.com
Hi,

Technically yes, but it doesn’t fix my problem of wanting to understand the oscar API :).

So, I’d still like to understand of overriding the dashboard app as I did it *should* work. It seems that it should - that is the method I use to override the search app, for example.

Because I’m getting heavily into Oscar for the current project, I’m not only interested in “putting out the fire”, but rather, understanding the hows and whys. The documentation around this is really hard to follow, and lacking information.
> --
> https://github.com/tangentlabs/django-oscar
> http://django-oscar.readthedocs.org/en/latest/
> https://twitter.com/django_oscar
> ---
> You received this message because you are subscribed to a topic in the Google Groups "django-oscar" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/topic/django-oscar/tfAkJFARTGM/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to django-oscar...@googlegroups.com.
> Visit this group at http://groups.google.com/group/django-oscar.
> To view this discussion on the web visit https://groups.google.com/d/msgid/django-oscar/5357811D.8010505%40tangentsnowball.com.

Izidor Matušov

unread,
Apr 23, 2014, 11:45:24 AM4/23/14
to django...@googlegroups.com
On 23/04/14 10:11, Paul Walsh wrote:
> Because I’m getting heavily into Oscar for the current project, I’m not only interested in “putting out the fire”, but rather, understanding the hows and whys. The documentation around this is really hard to follow, and lacking information.

Fully understand you, let's fix the documentation flaw.

The loading happens using get_classes [0]. The method tries to mimic
Django's get_model for dynamic loading of components. Maik and I tweak
get_classes last couple weaks, trying to get it right. (Notice that
there are quite many comments trying to document how it works)

Get class is used afterwardson many places, including finding dashboard
app [1] BTW: Do you include Oscar's app in your urlpatterns?

0:
https://github.com/tangentlabs/django-oscar/blob/master/oscar/core/loading.py#L70
1: https://github.com/tangentlabs/django-oscar/blob/master/oscar/app.py#L23

Paul Walsh

unread,
Apr 24, 2014, 1:41:57 AM4/24/14
to django...@googlegroups.com
If you look below, you’ll see I have a file called ”hamigdalor.app” which provides my own custom shop app, and that is where I override Oscar’s search app, and *attempt* to override the dashboard in exactly the same way.

I then pass that app to the root urlpatterns.

The search override works, the dashboard override doesn’t.

In general I know about get_class and I had a brief look at the code, but there is a lot happening in Oscar with the way app overrides work (which I think is a great idea, by the way), so, it still feels somewhat magical to me right now.
> --
> https://github.com/tangentlabs/django-oscar
> http://django-oscar.readthedocs.org/en/latest/
> https://twitter.com/django_oscar
> ---
> You received this message because you are subscribed to a topic in the Google Groups "django-oscar" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/topic/django-oscar/tfAkJFARTGM/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to django-oscar...@googlegroups.com.
> Visit this group at http://groups.google.com/group/django-oscar.
> To view this discussion on the web visit https://groups.google.com/d/msgid/django-oscar/5357E014.9030105%40tangentsnowball.com.

Maik Hoepfel

unread,
Apr 30, 2014, 9:19:25 AM4/30/14
to django...@googlegroups.com
Hi Paul,

> I have no show_urls management command
It's part of django-extensions and very useful! :)

> understanding the hows and whys. The documentation around
> this is really hard to follow, and lacking information.

Any pointers regarding this are much appreciated. I find it hard to
write good docs these days, because I'm not sure what parts of Oscar are
confusing to people. If you can give me some sample questions or ideas,
I'm happy to write up some docs.

--

For the future, may I suggest you put your code into Github Gists? That
gives us syntax highlighting, and inline commenting if I'm not mistaken.

--

It seems to be you want to add a new app in the dashboard, so have it
sit alongside e.g. 'dashboard.catalogue' and 'dashboard.orders'.

So you correctly created an app 'dashboard.staffpicks'. Fine. This
should get added to your INSTALLED_APPS, because anything that interacts
with "get_classes magic" needs to live there, and because it's generally
a good idea anyway.

The problem you're trying to solve now is that the URLs for that app
aren't getting picked up. (Observe that it works if you put it in your
project root URLs). When Oscar URLs are gathered, it walks down a tree
of Application instances, starting with your (or Oscar's) root
application. Your root application is that one liner in your project
root urls.py that all Oscar URLs live under.

To get the URLs for your new dashboard application picked up, get_urls
of your new Application instance needs to be called. It is only called
if you wire it up at it's parent Application instance, which in this
case should be DashboardApplication.

This means we need to override DashboardApplication. As with replacing
any class in Oscar, you first have to determine the name of the Oscar
app that the class lives in, and then have an app with the same name. As
DashboardApplication lives in oscar.apps.dashboard.app, you need an app
called 'yourproject.dashboard' and, crucially, have that listed
*instead* of 'oscar.apps.dashboard' in your INSTALLED_APPS. That's what
the override section for get_core_apps() is for. It should look
something like this:

INSTALLED_APPS = [
# stuff
'hamigdalor.apps.dashboard.staffpicks’,
# stuff
] + get_core_apps('hamigdalor.apps.dashboard', )


And then DashboardApplication should look something like this (not checked):

from oscar.apps.dashboard.app import DashboardApplication as
OscarDashboardApplication
from hamigdalor.apps.dashboard.staffpicks.app import application as
staffpicks_app

class DashboardApplication(OscarDashboardApplication):
staffpicks_app = staffpicks_app

def get_urls(self):
urls = [
url(r'^$', self.index_view.as_view(), name='index'),
url(r'^catalogue/', include(self.catalogue_app.urls)),
url(r'^reports/', include(self.reports_app.urls)),
url(r'^orders/', include(self.orders_app.urls)),
url(r'^users/', include(self.users_app.urls)),
url(r'^content-blocks/', include(self.promotions_app.urls)),
url(r'^pages/', include(self.pages_app.urls)),
url(r'^partners/', include(self.partners_app.urls)),
url(r'^offers/', include(self.offers_app.urls)),
url(r'^ranges/', include(self.ranges_app.urls)),
url(r'^reviews/', include(self.reviews_app.urls)),
url(r'^vouchers/', include(self.vouchers_app.urls)),
url(r'^comms/', include(self.comms_app.urls)),

# your app!
url(r'^staff/', include(self.staffpicks_ap.urls)),
]
return self.post_process_urls(urls)

application = DashboardApplication()

--

Your DashboardApplication will get picked up automatically by Oscar
because the root application loads it via get_classes and you've
overridden it in your INSTALLED_APPS correctly:
https://github.com/tangentlabs/django-oscar/blob/master/oscar/app.py#L23

Note that you'll never need to use get_classes for your own classes,
because you can just import directly.






Maik Hoepfel

unread,
Apr 30, 2014, 9:22:16 AM4/30/14
to django...@googlegroups.com
I accidentally sent the email early, but was done anyway! :)

Good luck! Let me know if you have further questions. I'll try to
distill some of this into better docs, too.

Cheers,

Maik

Paul Walsh

unread,
May 4, 2014, 3:39:59 AM5/4/14
to django...@googlegroups.com
Hey Maik,

Ok, I'm back on this now.

I see, according to your post, that each new dashboard app needs to be explicitly in INSTALLED_APPS. 

I'm going through it all now and will update. Meanwhile, I put my current code in a gist as requested:

Paul Walsh

unread,
May 4, 2014, 4:11:01 AM5/4/14
to django...@googlegroups.com
Ok,

I've followed all the instructions here as best as I can, but I can't get my new dashboard app to appear in the dashboard with those instructions.

Here is my updated code:


I'm hoping we can work through this not just for my benefit, but so we can clarify the docs for anyone who is working on integrating custom apps.

David Winterbottom

unread,
May 6, 2014, 5:46:03 AM5/6/14
to django-oscar
It's hard to tell what's wrong from first glance.

Here's what I would look at using PDB:

Is your node returned from 'create_menu' here:

Does it get filtered out? Ie, is it in the visible_nodes var:

Assuming it gets filtered, step through the filtering logic to see why:



--
You received this message because you are subscribed to the Google Groups "django-oscar" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-oscar...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
David Winterbottom
Technical Director

Tangent Labs
84-86 Great Portland Street
London W1W 7NR
England, UK

Paul Walsh

unread,
May 7, 2014, 8:16:52 AM5/7/14
to django...@googlegroups.com, david.win...@tangentlabs.co.uk
Hi David,

Thanks for chiming in. I actually just sat down with Maik and we got to the problem.

Hopefully he or I will update the docs soon, but it all came down to this line:


It is unclear that Dashboard apps are already namespaced under "dashboard:". So, while I expected my app to be available at:

"staffpick-dashboard:list"

is was actually at:

"dashboard:staffpick-dashboard:list"

Further, due to the way that url names are parsed in the permissions logic of the dashboard, it is not safe to have multiple ":" in a url name. So, at present, Dashboard apps need to have `name = None` and should be access at `dashboard:NAME_OF_ROUTE`

Best,

Paul.

David Winterbottom

unread,
May 7, 2014, 8:26:09 AM5/7/14
to django-oscar
That is quite subtle - I'm glad you got to the bottom of it though.



For more options, visit https://groups.google.com/d/optout.



--
David Winterbottom
Technical Director

Tangent Snowball
Reply all
Reply to author
Forward
0 new messages