19. 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:
19.1. Django-SHOP specific settings¶
19.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.
19.1.2. Site Framework¶
You should always activate Django’s site framework and set a default for
SITE_ID = 1
19.1.3. 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 its 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.
19.1.4. Authentication Backends¶
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
'allauth.account.auth_backends.AuthenticationBackend',
]
19.1.5. 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.
Unless amounts never reach a thousand, it is advised to activate a separator for better readability.
USE_THOUSAND_SEPARATOR = True
Outside of the US, it generally is a good idea to activate localization for numeric types.
USE_L10N = True
19.1.6. 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.
19.1.7. 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 afterdjango.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 django-CMS.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. This setting including submodules can be removed, if all templates are created manually.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
andrest_auth
, required, add the REST functionality to the django-SHOP framework.django_fsm
andfsm_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
andtreebeard
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
andeasy_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.
19.1.8. 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’sreverse
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.
19.1.9. 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',
]
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 = [
('node_modules', '/path/to/project/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'),
)
- The string provided by
NODE_MODULES_URL
is used by the special functionget-setting()
in the provided SASS files. SASS_PROCESSOR_INCLUDE_DIRS
extends the list of folders to look for@import ...
statements in the provided SASS files.
19.1.10. 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.ng_model_options',
),
},
}]
shop.context_processors.customer
adds the Customer object to the rendering context.
shop.context_processors.ng_model_options
adds the AngularJS specific settings
to the rendering context.
19.1.11. 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
19.1.12. Email settings¶
Since django-SHOP communicates with its customers via email, having a working 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 via 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'
19.1.13. Session Handling¶
For performance reasons it is recommended to use a memory based session store such as Redis, rather than a database or disk based store.
SESSION_ENGINE = 'redis_sessions.session'
SESSION_SAVE_EVERY_REQUEST = True
SESSION_REDIS_PREFIX = 'myshop-session'
SESSION_REDIS_DB = 0
19.1.14. Caching Backend¶
For performance reasons it is recommended to use a memory based cache such as Redis, rather than a disk based store. In comparison to memcached, Redis can invalidate cache entries using keys with wildcards, which is a big advantage in django-SHOP.
CACHES = {
'default': {
'BACKEND': 'redis_cache.RedisCache',
'LOCATION': os.environ.get('REDIS_LOCATION', 'redis://localhost:6379/0'),
'KEY_PREFIX': 'myshop-cache',
},
}
CACHE_MIDDLEWARE_ALIAS = 'default'
CACHE_MIDDLEWARE_SECONDS = 3600
CACHE_MIDDLEWARE_KEY_PREFIX = 'myshop-cache'
19.2. Internationalisation Support¶
Always localize decimal numbers unless you operate you site in the United States:
USE_L10N = True
These settings for internationalisation are known to work in combination with django-cms and django-parler.
USE_I18N = True
LANGUAGE_CODE = 'en'
LANGUAGES = [
('en', "English"),
('de', "Deutsch"),
]
PARLER_DEFAULT_LANGUAGE = 'en'
PARLER_LANGUAGES = {
1: [
{'code': 'de'},
{'code': 'en'},
],
'default': {
'fallbacks': ['de', 'en'],
},
}
CMS_LANGUAGES = {
'default': {
'fallbacks': ['en', 'de'],
'redirect_on_fallback': True,
'public': True,
'hide_untranslated': False,
},
1: [{
'public': True,
'code': 'en',
'hide_untranslated': False,
'name': 'English',
'redirect_on_fallback': True,
}, {
'public': True,
'code': 'de',
'hide_untranslated': False,
'name': 'Deutsch',
'redirect_on_fallback': True,
},]
}
19.2.1. 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': '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
19.2.2. 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
cascade_workarea_glossary = {
'breakpoints': ['xs', 'sm', 'md', 'lg'],
'container_max_widths': {'xs': 750, 'sm': 750, 'md': 970, 'lg': 1170},
'fluid': False,
'media_queries': {
'xs': ['(max-width: 768px)'],
'sm': ['(min-width: 768px)', '(max-width: 992px)'],
'md': ['(min-width: 992px)', '(max-width: 1200px)'],
'lg': ['(min-width: 1200px)'],
},
}
CMS_PLACEHOLDER_CONF = {
'Breadcrumb': {
'plugins': ['BreadcrumbPlugin'],
'parent_classes': {'BreadcrumbPlugin': None},
'glossary': cascade_workarea_glossary,
},
'Commodity Details': {
'plugins': ['BootstrapContainerPlugin', 'BootstrapJumbotronPlugin'],
'parent_classes': {
'BootstrapContainerPlugin': None,
'BootstrapJumbotronPlugin': None,
},
'glossary': cascade_workarea_glossary,
},
'Main Content': {
'plugins': ['BootstrapContainerPlugin', 'BootstrapJumbotronPlugin'],
'parent_classes': {
'BootstrapContainerPlugin': None,
'BootstrapJumbotronPlugin': None,
'TextLinkPlugin': ['TextPlugin', 'AcceptConditionPlugin'],
},
'glossary': cascade_workarea_glossary,
},
'Static Footer': {
'plugins': ['BootstrapContainerPlugin', ],
'parent_classes': {
'BootstrapContainerPlugin': None,
},
'glossary': cascade_workarea_glossary,
},
}
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.icon',
'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',
],
'alien_plugins': ['TextPlugin', 'TextLinkPlugin', 'AcceptConditionPlugin'],
'bootstrap3': {
'template_basedir': 'angular-ui',
},
'plugins_with_sharables': {
'BootstrapImagePlugin': ['image_shapes', 'image_width_responsive', 'image_width_fixed',
'image_height', 'resize_options'],
'BootstrapPicturePlugin': ['image_shapes', 'responsive_heights', 'image_size', 'resize_options'],
},
'bookmark_prefix': '/',
'segmentation_mixins': [
('shop.cascade.segmentation.EmulateCustomerModelMixin', 'shop.cascade.segmentation.EmulateCustomerAdminMixin'),
],
'allow_plugin_hiding': True,
}
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
.
Django-SHOP uses AngularJS rather than jQuery to control its 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.
19.2.3. CK Text Editor settings¶
By default, django-CMS uses the CKEditor plugin which can be heavily configured. Settings which have shown to be useful are:
CKEDITOR_SETTINGS_CAPTION = {
'language': '{{ language }}',
'skin': 'moono',
'height': 70,
'toolbar_HTMLField': [
['Undo', 'Redo'],
['Format', 'Styles'],
['Bold', 'Italic', 'Underline', '-', 'Subscript', 'Superscript', '-', 'RemoveFormat'],
['Source']
],
}
CKEDITOR_SETTINGS_DESCRIPTION = {
'language': '{{ language }}',
'skin': 'moono',
'height': 250,
'toolbar_HTMLField': [
['Undo', 'Redo'],
['cmsplugins', '-', 'ShowBlocks'],
['Format', 'Styles'],
['TextColor', 'BGColor', '-', 'PasteText', 'PasteFromWord'],
['Maximize', ''],
'/',
['Bold', 'Italic', 'Underline', '-', 'Subscript', 'Superscript', '-', 'RemoveFormat'],
['JustifyLeft', 'JustifyCenter', 'JustifyRight'],
['HorizontalRule'],
['NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Table'],
['Source']
],
}
19.2.4. Media assets handling¶
Django-CMS and django-SHOP rely on django-filer in combination with easy-thumbnails to manage the media assets.
MEDIA_ROOT = '/path/to/project/media'
MEDIA_URL = '/media/'
FILER_ALLOW_REGULAR_USERS_TO_ADD_ROOT_FOLDERS = True
FILE_UPLOAD_MAX_MEMORY_SIZE = 5242880
THUMBNAIL_OPTIMIZE_COMMAND = {
'gif': '/usr/bin/optipng {filename}',
'jpeg': '/usr/bin/jpegoptim {filename}',
'png': '/usr/bin/optipng {filename}'
}
THUMBNAIL_PRESERVE_EXTENSIONS = True
THUMBNAIL_PROCESSORS = [
'easy_thumbnails.processors.colorspace',
'easy_thumbnails.processors.autocrop',
'filer.thumbnail_processors.scale_and_crop_with_subject_location',
'easy_thumbnails.processors.filters',
]
all settings are explained in detail in the documentation of django-filer and easy-thumbnails.
19.2.5. Full Text Search¶
Presuming that you installed and run an ElasticSearchEngine server, configure Haystack:
HAYSTACK_CONNECTIONS = {
'default': {
'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine',
'URL': 'http://localhost:9200/',
'INDEX_NAME': 'my_prefix-en',
},
}
If you want to index other natural language, say German, add another prefix:
HAYSTACK_CONNECTIONS = {
...
'de': {
'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine',
'URL': 'http://localhost:9200/',
'INDEX_NAME': 'my_prefix-de',
}
}
HAYSTACK_ROUTERS = ('shop.search.routers.LanguageRouter',)
19.2.6. 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.
19.2.7. 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'