3

I'm developing an ecommerce website using django-oscar 2.0.1.

I would like to change the url to access catalogue (as described here in the documentation), but I always get this error :

**NoReverseMatch at / 'customer' is not a registered namespace.**.

I know I'm not the only one who get this error (Django Oscar change URL pattern) but the solution proposed is this post doesn't work for me (perhaps because django-oscar version was 1.6.5 at this time ?).

So, here is the step I followed based on django-oscar documentation :

  • I created a new project in a python venv with django-oscar and all the dependencies.
  • I forked the catalogue app
python manage.py oscar_fork_app catalogue forkedApps
  • Edited the installed Apps
    #'oscar.apps.catalogue',
    'forkedApps.catalogue.apps.CatalogueConfig',
    'oscar.apps.catalogue.reviews',

Here is the structure of the project :

project
    > forkedApps
        > catalogue
            . __init__.py
            . admin.py
            . apps.py
            . models.py
    > project
        . __init__.py
        . settings.py
        . urls.py
        . wsgi.py
  • I tried to change catalogue base URL from /catalogue to /cata :

Forked catalogue

    # forkedApps/catalogue/apps.py

    import oscar.apps.catalogue.apps as apps
    from oscar import config
    from django.conf.urls import url

    from django.views.generic.base import RedirectView
    from django.urls import reverse_lazy

    class CatalogueConfig(apps.CatalogueConfig):
        name = 'forkedApps.catalogue'

    class MyShop(config.Shop):

        # Override get_urls method
        def get_urls(self):
            from django.contrib.auth import views as auth_views

            from oscar.views.decorators import login_forbidden
            urlpatterns = [
                url(r'^cata/', self.catalogue_app.urls),
                url(r'^$', RedirectView.as_view(url=reverse_lazy('catalogue:index')), name='home'),
                url(r'^basket/', self.basket_app.urls),
                #...all other urls
            ]
            return urlpatterns

Project init

    #project/project/__init__.py

    default_app_config = 'forkedApps.catalogue.apps.MyShop'

Project url

    #project/project/urls.py

    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('', include(apps.get_app_config('oscar').urls[0])),
        path('', include(apps.get_app_config('catalogue').urls[0])),
        ### Does catalogue refers to my forked catalogue ? ###
    ]

And when I run the server I got this error :

raise NoReverseMatch("%s is not a registered namespace" % key) django.urls.exceptions.NoReverseMatch: 'customer' is not a registered namespace

Do you have any idea about what I missed ?

SOLUTION :

I created an APP called 'oscar_url' (arbitrary name) and I added it to INSTALLED_APPS

oscar_url init

    #project/oscar_url/__init__.py

    default_app_config = 'oscar_url.apps.MyShop'

oscar_url apps

    #project/oscar_url/apps.py
    import oscar.config as apps
    from django.views.generic.base import RedirectView
    from django.urls import reverse_lazy
    from django.conf.urls import url

    class MyShop(apps.Shop):
        name = 'oscar_url'

        def get_urls(self):
            from django.contrib.auth import views as auth_views

            from oscar.views.decorators import login_forbidden
            urlpatterns = [
                url(r'^cata/', self.catalogue_app.urls),
                url(r'^$', RedirectView.as_view(url=reverse_lazy('catalogue:index')), name='home'),
                url(r'^basket/', self.basket_app.urls),
                url(r'^checkout/', self.checkout_app.urls),
                #all others urls...
            ]
            return urlpatterns

And I modified the project urls :

Project url

    #project/project/urls.py

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

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

        #path('', include(apps.get_app_config('oscar').urls[0])),
        path('', include(apps.get_app_config('oscar_url').urls[0])),
    ]
Mairkur
  • 177
  • 1
  • 15
  • I used the same way as defined in the solution part, unfortunately, I was not able to change any view. Let say I want to override the dashboard view and add some custom stuff. Were you able to achieve this through the way you described above? Thanks. – Sabuhi Shukurov Apr 06 '20 at 14:21
  • Okay, I solved the problem, here how is the solution: after forking apps, you apps.py in the forked application.Let say I have forked dashboard and it has apps.py automatically created with the following: class DashboardConfig(apps.DashboardConfig): name = 'oscar_apps.dashboard' import your vies inside ready method and override ready and get_urls methods. Thanks. – Sabuhi Shukurov Apr 06 '20 at 14:53

1 Answers1

1

There are a couple of things here:

  1. You have defined a MyShop class, but you are not loading it anywhere. You need to include this app in your INSTALLED_APPS.

    Note that in this context it probably doesn't make sense to have MyShop living inside your catalogue app - this shop app is for your entire project, not just for the catalogue.

  2. In your project URLs, you need to load this new app's configuration instead of Oscar's:

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

    Where you would set name = 'name_of_your_app' in MyShop.

solarissmoke
  • 30,039
  • 14
  • 71
  • 73
  • Where is the best place to store MyShop ? I tried to fork oscar (with oscar_fork_app oscar) but I get some errors when I try to replace it. – Mairkur Sep 11 '19 at 11:36
  • You can't fork the root app. Just store `MyShop` in the root of your project - e.g., `project/apps.py`. – solarissmoke Sep 11 '19 at 12:10
  • I created a new app called 'django_url' for that. It works well without replacing oscar in installed apps. – Mairkur Sep 11 '19 at 12:10
  • Great. My original answer was slightly wrong (you still need `oscar` in `INSTALLED_APPS` otherwise other things will break) I've edited it slightly. – solarissmoke Sep 11 '19 at 12:14