17. Configuration and Settings

The django-SHOP framework itself, requires only a few configuration directives. However, since each e-commerce site built around django-SHOP consists of the merchant’s own project, plus a collection of third party Django apps, here is a summary of mandatory and some optional configuration settings:

17.1. Django-SHOP specific settings

17.1.1. App Label

This label is required internally to configure the name of the database tables used in the merchant’s implementation.

SHOP_APP_LABEL = 'myshop'

There is no default setting.

17.1.2. Alternative User Model

Django’s built-in User model lacks a few features required by django-SHOP, mainly the possibility to use the email address as the login credential. This overridden model is 100% field compatible to Django’s internal model and even reuses it’s own database table, namely auth_user.

AUTH_USER_MODEL = 'email_auth.User'

Since this user model intentionally does not enforce uniqueness on the email address, Django would complain if we do not silence this system check:

SILENCED_SYSTEM_CHECKS = ('auth.W004')

For further information, please refer to the Customer Model documentation.

17.1.3. Authentication Backends

AUTHENTICATION_BACKENDS = (
    'django.contrib.auth.backends.ModelBackend',
    'allauth.account.auth_backends.AuthenticationBackend',
)

17.1.4. Currency

Unless Money types are specified explicitly, each project requires a default currency:

SHOP_DEFAULT_CURRENCY = 'EUR'

The typical format to render an amount is $ 1.23, but some merchant may prefer 1.23 USD. By using the configuration setting:

SHOP_MONEY_FORMAT = '{symbol} {amount}'

we my specify our own money rendering format, where {symbol} is €, $, £, etc. and {currency} is EUR, USD, GBP, etc.

17.1.5. Cart Modifiers

Each project requires at least one cart modifier in order to initialize the cart. In most implementations shop.modifiers.defaults.DefaultCartModifier is enough, but depending on the product models, the merchant’s may implement an alternative.

To identify the taxes in the cart, use one of the provided tax modifiers or implement a customized one.

Other modifiers may add extra payment and shipping costs, or rebate the total amount depending on whatever appropriate.

SHOP_CART_MODIFIERS = (
    'shop.modifiers.defaults.DefaultCartModifier',
    'shop.modifiers.taxes.CartExcludedTaxModifier',
    # other modifiers
)

For further information, please refer to the Cart Modifiers documentation.

17.1.6. Installed Django Applications

This is a configuration known to work. Special and optional apps are discussed below.

INSTALLED_APPS = (
    'django.contrib.auth',
    'email_auth',
    'polymorphic',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'djangocms_admin_style',
    'django.contrib.admin',
    'django.contrib.staticfiles',
    'django.contrib.sitemaps',
    'djangocms_text_ckeditor',
    'django_select2',
    'cmsplugin_cascade',
    'cmsplugin_cascade.clipboard',
    'cmsplugin_cascade.sharable',
    'cmsplugin_cascade.extra_fields',
    'cmsplugin_cascade.segmentation',
    'cms_bootstrap3',
    'adminsortable2',
    'rest_framework',
    'rest_framework.authtoken',
    'rest_auth',
    'django_fsm',
    'fsm_admin',
    'djng',
    'cms',
    'menus',
    'treebeard',
    'compressor',
    'sekizai',
    'sass_processor',
    'django_filters',
    'filer',
    'easy_thumbnails',
    'easy_thumbnails.optimize',
    'parler',
    'post_office',
    'haystack',
    'shop',
    'my_shop_implementation',
)
  • email_auth optional but recommended, overrides the built-in authentification. It must be located after django.contrib.auth.
  • polymorphic only required, if the site requires more than one type of product model. It presumes that django-polymorphic is installed.
  • djangocms_text_ckeditor optionally adds a WYSIWYG HTML editor which integrates well with djangoCMS.
  • django_select2 optionally adds a select field to Django’s admin, with integrated autocompletion. Very useful for addings links to products manually. It presumes that django-select2 is installed.
  • cmsplugin_cascade adds the functionality to add CMS plugins, as provided by django-SHOP, to arbitrary CMS placeholders.
  • cmsplugin_cascade.clipboard allows the site administrator to copy a set of plugins in one installation and paste it into the placeholder of another one.
  • cmsplugin_cascade.sharable allows the site administrator to share a preconfigurable set of plugin attributes into an alias, to be reused by many plugins of the same type.
  • cmsplugin_cascade.extra_fields allows the site administrator to add arbitrary CSS classes, styles and ID-fields to entitled plugins.
  • cmsplugin_cascade.segmentation allows to segment a set of plugins into logical units.
  • cms_bootstrap3 adds some templates and templatetags to render Bootstrap 3 styled menus and navigation bars.
  • adminsortable2 allows the site administrator to sort various items in Django’s administration backend.
  • rest_framework, rest_framework.authtoken and rest_auth, required, add the REST functionality to the django-SHOP framework.
  • django_fsm and fsm_admin, required, add the Finite State Machine to the django-SHOP framework.
  • djng only required for installations using AngularJS, which is the recommended JavaScript framework. It adds the interface layer between Django and AngularJS and presumes that django-angular is installed.
  • cms, menus and treebeard are required if django-SHOP is used in combination with djangoCMS.
  • compressor, highly recommended. Concatenates and minifies CSS and JavaScript files on production systems. It presumes that django-compressor is installed.
  • sekizai, highly recommended, allows the template designer to group CSS and JavaScript file includes. It presumes that django-sekizai is installed.
  • sass_processor, optional but recommended, used to convert SASS into pure CSS together with debugging information. It presumes that django-sass-processor is installed.
  • django_filters, optionally used to filter products by their attributes using request parameters.
  • filer, highly recommended, manage your media files in Django. It presumes that django-filer is installed.
  • easy_thumbnails and easy_thumbnails.optimize, highly recommended, handle thumbnail generation and optimization. It presumes that easy-thumbnails is installed.
  • parler is an optional framework which handles the translation of models fields into other natural languages.
  • post_office highly recommended. An asynchronous mail delivery application which does not interrupt the request-response cycle when sending mail.
  • haystack optional, handles the interface between Django and Elasticsearch – a full-text search engine. It presumes a running and available instance of ElasticSearch and that django-haystack and drf-haystack is installed.
  • shop the django-SHOP framework.
  • my_shop_implementation replace this by the merchant’s implementation of his shop.

17.1.7. Middleware Classes

This is a configuration known to work. Special middleware classes are discussed below.

MIDDLEWARE_CLASSES = (
    'djng.middleware.AngularUrlMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'shop.middleware.CustomerMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.gzip.GZipMiddleware',
    'shop.middleware.MethodOverrideMiddleware',
    'cms.middleware.language.LanguageCookieMiddleware',
    'cms.middleware.user.CurrentUserMiddleware',
    'cms.middleware.page.CurrentPageMiddleware',
    'cms.middleware.toolbar.ToolbarMiddleware',
)
  • djng.middleware.AngularUrlMiddleware adds a special router, so that we can use Django’s reverse function from inside JavaScript. Only required in conjunction with django-angular.
  • shop.middleware.CustomerMiddleware add the Customer object to each request.
  • shop.middleware.MethodOverrideMiddleware transforms PUT requests wrapped as POST requests back into the PUT method. This is required for compatibility with some JS frameworks and proxies.

17.1.8. Static Files

If compressor and/or sass_processor are part of INSTALLED_APPS, add their finders to the list of the default STATICFILES_FINDERS:

STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
    'sass_processor.finders.CssFinder',
    'compressor.finders.CompressorFinder',
)

Since django-SHOP requires a few third party packages, which are not available from PyPI, they instead must be installed via npm install. In order to make these files available to our Django application, we use the configuration setting:

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
    ('node_modules', os.path.join(PROJECT_ROOT, 'node_modules')),
)

Some files installed by npm are processed by django-sass-processor and hence their path must be made available:

NODE_MODULES_URL = STATIC_URL + 'node_modules/'

SASS_PROCESSOR_INCLUDE_DIRS = (
    os.path.join(PROJECT_ROOT, 'node_modules'),
)

17.1.9. Template Context Processors

Templates rendered by the django-SHOP framework require some additional objects or configuration settings. Add them to each template using these context processors:

TEMPLATES = [{
    ...
    'OPTIONS': {
        'context_processors': (
            ...
            'shop.context_processors.customer',
            'shop.context_processors.version',
            'shop.context_processors.ng_model_options',
        ),
    },
}]

shop.context_processors.customer adds the Customer object to the rendering context.

shop.context_processors.version adds the Django version to the rendering context.

shop.context_processors.ng_model_options adds the AngularJS specific settings to the rendering context.

17.1.10. Configure the Order Workflow

The ordering workflow can be configured using a list or tuple of mixin classes.

SHOP_ORDER_WORKFLOWS = (
    'shop.payment.defaults.PayInAdvanceWorkflowMixin',
    'shop.shipping.defaults.CommissionGoodsWorkflowMixin',
    # other workflow mixins
)

This prevents to display all transitions configured by the workflow mixins inside the administration backend:

FSM_ADMIN_FORCE_PERMIT = True

17.1.11. Email settings

Having w orking outgoing e-mail service is a fundamental requirement for django-SHOP. Adopt these settings to your configuration. Please remember that e-mail is sent asynchronously using django-post_office.

EMAIL_HOST = ‘smtp.example.com’ EMAIL_PORT = 587 EMAIL_HOST_USER = 'no-reply@example.com‘ EMAIL_HOST_PASSWORD = ‘smtp-secret-password’ EMAIL_USE_TLS = True DEFAULT_FROM_EMAIL = ‘My Shop <no-reply@example.com>’ EMAIL_REPLY_TO = 'info@example.com‘ EMAIL_BACKEND = ‘post_office.EmailBackend’

17.1.12. REST Framework

The REST framework requires special settings. We namely must inform it how to serialize our special Money type:

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (
        'shop.rest.money.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ),
    'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',),
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 12,
}

SERIALIZATION_MODULES = {'json': str('shop.money.serializers')}

Since the client side is not allowed to do any price and quantity computations, Decimal values are transferred to the client using strings. This also avoids nasty rounding errors.

COERCE_DECIMAL_TO_STRING = True

17.1.13. Django-CMS and Cascade settings

Django-SHOP requires at least one CMS template. Assure that it contains a placeholder able to accept

CMS_TEMPLATES = (
    ('myshop/pages/default.html', _("Default Page")),
)

CMS_PERMISSION = False

Django-SHOP enriches djangocms-cascade with a few shop specific plugins.

from cmsplugin_cascade.extra_fields.config import PluginExtraFieldsConfig

CMSPLUGIN_CASCADE_PLUGINS = ('cmsplugin_cascade.segmentation', 'cmsplugin_cascade.generic',
    'cmsplugin_cascade.link', 'shop.cascade', 'cmsplugin_cascade.bootstrap3',)

CMSPLUGIN_CASCADE = {
    'link_plugin_classes': (
        'shop.cascade.plugin_base.CatalogLinkPluginBase',
        'cmsplugin_cascade.link.plugin_base.LinkElementMixin',
        'shop.cascade.plugin_base.CatalogLinkForm',
    ),
    'dependencies': {
        'shop/js/admin/shoplinkplugin.js': 'cascade/js/admin/linkpluginbase.js',
    },
    'alien_plugins': ('TextPlugin', 'TextLinkPlugin',),
    'bootstrap3': {
        'template_basedir': 'angular-ui',
    },
    'plugins_with_extra_fields': {
        'ExtraAnnotationFormPlugin': PluginExtraFieldsConfig(),
        'ShopProceedButton': PluginExtraFieldsConfig(),
        'ShopAddToCartPlugin': PluginExtraFieldsConfig(),
    },
    'segmentation_mixins': (
        ('shop.cascade.segmentation.EmulateCustomerModelMixin',
         'shop.cascade.segmentation.EmulateCustomerAdminMixin'),
    ),
    'plugins_with_extra_render_templates': {
        'CustomSnippetPlugin': [
            ('shop/catalog/product-heading.html', _("Product Heading"))
        ],
    },
}

Since we want to add arbitrary links onto the detail view of a product, django-SHOP offers a modified link plugin. This has to be enabled using the 3-tuple link_plugin_classes. There is also a JavaScript helper shop/js/admin/shoplinkplugin.js, which depends on another JavaScript file.

Django-SHOP uses with AngularJS rather than jQuery to control it’s dynamic HTML widgets. We therefore have to override the default with this settings: CMSPLUGIN_CASCADE['bootstrap3']['template_basedir'].

For a detailed explanation of these configuration settings, please refer to the documentation of djangocms-cascade.

17.1.15. AngularJS specific settings

The cart’s totals are updated after an input field has been changed. For usability reasons it makes sense to delay this, so that only after a certain time of inactivity, the update is triggered.

SHOP_ADD2CART_NG_MODEL_OPTIONS = "{updateOn: 'default blur', debounce: {'default': 500, 'blur': 0}}"

This configuration updates the cart after changing the quantity and 500 milliseconds of inactivity or field blurring. It is used by the “Add to cart” form.

SHOP_EDITCART_NG_MODEL_OPTIONS = "{updateOn: 'default blur', debounce: {'default': 2500, 'blur': 0}}"

This configuration updates the cart after changing any of the product’s quantities and 2.5 seconds of inactivity or field blurring. It is used by the “Edit cart” form.

17.1.16. Select2 specific settings

django-select2 adds a configurable autocompletion field to the project.

Change the include path to a local directory, if you prefer to install the JavaScript dependencies via npm instead of relying on a preconfigured CDN:

SELECT2_CSS = 'node_modules/select2/dist/css/select2.min.css'
SELECT2_JS = 'node_modules/select2/dist/js/select2.min.js'