Customizing Oscar API

By using the django-rest-framework life has become easy, at least for customizing the Oscar API. Oscar API exists of a collection of views and serializers which can be overriden by following the steps below.

Note

In oscar you can fork an app to easily customize only the things you want to change.

Oscar API is using the basics of this so you can see Oscar API as one of the apps you customized just like in Oscar. Each Oscar app (or forked app) has a app.py which manages the url’s to your custom views.

In Oscar API the entry point of this is oscarapi.app:RESTApiApplication.

In your own app, you can extend this class, and override some of the urls to direct them to your own views. You can subclass any of the views in oscarapi, or just write your own from scratch.

So, to modify some of the functionality in oscarapi, do the following:

  1. In your project, create a new django app with manage.py startapp mycustomapi.
  2. In your app, create a file named app.py and in there extend oscarapi.app:RESTApiApplication, like the following example:
from oscarapi.app import RESTApiApplication

    class MyRESTApiApplication(RESTApiApplication):

        def get_urls(self):
            urls = super(MyRESTApiApplication, self).get_urls()
            return urls

application = MyRESTApiApplication()
  1. Make sure you use this application instead of the app shipped with oscarapi in your urls.py:
from django.conf.urls import include, url
from django.contrib import admin

from mycustomapi.app import application as api
from oscar.app import application as oscar

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^api/', include(api.urls)),
    url(r'', include(oscar.urls)),

]

Note

If you think that this is not changing anything (yet) then this is correct, see below.

  1. Include your own app in INSTALLED_APPS instead of django-oscar-api (and add django-oscar-api to your app’s dependencies) and see if this works.
  2. Add a serializer and a view for the parts you want to change. In this example, we will override the ProductList view so we can specify a different ProductLinkSerializer which includes images and the price as well:

serializers.py

from rest_framework import serializers

from oscar.core.loading import get_class

from oscarapi.serializers.checkout import PriceSerializer
from oscarapi.serializers.product import (
    ProductImageSerializer, ProductLinkSerializer
)


Selector = get_class('partner.strategy', 'Selector')


class MyProductLinkSerializer(ProductLinkSerializer):
    images = ProductImageSerializer(many=True, required=False)
    price = serializers.SerializerMethodField()

    class Meta(ProductLinkSerializer.Meta):
        fields = ('url', 'id', 'title', 'images', 'price')

    def get_price(self, obj):
        request = self.context.get("request")
        strategy = Selector().strategy(
            request=request, user=request.user)
        ser = PriceSerializer(
            strategy.fetch_for_product(obj).price,
            context={'request': request})
        return ser.data

views.py

from oscarapi.views import basic

from .serializers import MyProductLinkSerializer


class ProductList(basic.ProductList):
    serializer_class = MyProductLinkSerializer
  1. Adjust your app.py with your custom urls:
from django.conf.urls import url

from mycustomapi import views

from oscarapi.app import RESTApiApplication


class MyRESTApiApplication(RESTApiApplication):

    def get_urls(self):
        urls = [url(
            r'^products/$',
            views.ProductList.as_view(), name='product-list')]

        return urls + super(MyRESTApiApplication, self).get_urls()

application = MyRESTApiApplication()
  1. Your urls.py still looks the same, as we have configured the override in app.py:
from django.conf.urls import include, url
from django.contrib import admin

from mycustomapi.app import application as api
from oscar.app import application as oscar

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^api/', include(api.urls)),
    url(r'', include(oscar.urls)),

]

The complete example above is available in the Github repository of Oscar API if you want to try it out.