django-multisite2


Namedjango-multisite2 JSON
Version 2.1.0 PyPI version JSON
download
home_pageNone
SummaryServe multiple sites from a single Django application
upload_time2025-07-18 21:16:04
maintainerNone
docs_urlNone
authorNone
requires_python>=3.12
licenseNone
keywords django nginx edc clinical trials research data management gunicorn deployment
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage
            |pypi| |actions| |codecov| |downloads| |maintainability| |black|



django_multisite2
=================

With ``django_multisite2`` a single instance of a Django project can serve multiple sites using a single settings file (multi-tenant). The current ``SITE_ID`` is extracted from the URL.

In ``settings``, the static ``SITE_ID`` is replaced with ``django_multisite2`` dynamic ``SiteID``::

    # settings.py
    SITE_ID = SiteID(default=1)

the dynamic ``SiteID`` behaves like an integer. When combined with ``django_multisite2`` middleware, ``SiteID`` will return the current ``SITE_ID`` based on the url. For example, each url below is an alias of the same server instance. With ``django_multisite2`` you might have something like this::

    # https://harare.example.com
    >>> from django.conf import settings
    >>> settings.SITE_ID
    10

    # https://kampala.example.com
    >>> from django.conf import settings
    >>> settings.SITE_ID
    20


Python 3.11+ Django 4.2+. New releases are cut from the ``main`` branch.

Older versions of Django are supported by the original `django-multisite`_ project.


Installation
============

Install with pip:

.. code-block::

    pip install django-multisite2


Replace your ``SITE_ID`` in ``settings.py`` to:

.. code-block::

    from multisite import SiteID
    SITE_ID = SiteID(default=1)


add to INSTALLED_APPS:

.. code-block::

    INSTALLED_APPS = [
        ...
        'django.contrib.sites',
        'multisite',
        ...
    ]


Edit settings.py MIDDLEWARE:

.. code-block::

    MIDDLEWARE = (
        ...
        'multisite.middleware.DynamicSiteMiddleware',
        ...
    )


Using a custom cache
--------------------
Append to settings.py, in order to use a custom cache that can be
safely cleared::

    # The cache connection to use for django-multisite.
    # Default: 'default'
    CACHE_MULTISITE_ALIAS = 'multisite'

    # The cache key prefix that django-multisite should use.
    # If not set, defaults to the KEY_PREFIX used in the defined
    # CACHE_MULTISITE_ALIAS or the default cache (empty string if not set)
    CACHE_MULTISITE_KEY_PREFIX = ''

If you have set CACHE\_MULTISITE\_ALIAS to a custom value, *e.g.*
``'multisite'``, add a separate backend to settings.py CACHES::

    CACHES = {
        'default': {
            ...
        },
        'multisite': {
            'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
            'TIMEOUT': 60 * 60 * 24,  # 24 hours
            ...
        },
    }


Domain fallbacks
----------------

By default, if the domain name is unknown, multisite will respond with
an HTTP 404 Not Found error. To change this behaviour, add to
settings.py::

    # The view function or class-based view that django-multisite will
    # use when it cannot match the hostname with a Site. This can be
    # the name of the function or the function itself.
    # Default: None
    MULTISITE_FALLBACK = 'django.views.generic.base.RedirectView

    # Keyword arguments for the MULTISITE_FALLBACK view.
    # Default: {}
    MULTISITE_FALLBACK_KWARGS = {'url': 'http://example.com/',
                                 'permanent': False}

Templates
---------

This feature has been removed in version 2.0.0.

If required, create template subdirectories for domain level templates (in a
location specified in settings.TEMPLATES['DIRS'].

Multisite's template loader will look for templates in folders with the names of
domains, such as::

    templates/example.com


The template loader will also look for templates in a folder specified by the
optional MULTISITE_DEFAULT_TEMPLATE_DIR setting, e.g.::

    templates/multisite_templates


Cross-domain cookie support
---------------------------

In order to support `cross-domain cookies`_ , for purposes like single-sign-on, prepend the following to the top of
settings.py MIDDLEWARE (MIDDLEWARE_CLASSES for Django < 1.10)::

    MIDDLEWARE = (
        'multisite.middleware.CookieDomainMiddleware',
        ...
    )

CookieDomainMiddleware will consult the `Public Suffix List`_
for effective top-level domains.
It caches this file
in the system's default temporary directory
as ``effective_tld_names.dat``.
To change this in settings.py::

    MULTISITE_PUBLIC_SUFFIX_LIST_CACHE = '/path/to/multisite_tld.dat'

By default,
any cookies without a domain set
will be reset to allow \*.domain.tld.
To change this in settings.py::

    MULTISITE_COOKIE_DOMAIN_DEPTH = 1  # Allow only *.subdomain.domain.tld

In order to fetch a new version of the list,
run::

    manage.py update_public_suffix_list


Post-migrate signal: post_migrate_sync_alias
--------------------------------------------
The ``post-migrate`` signal ``post_migrate_sync_alias`` is registered in the ``apps.py``. ``post_migrate_sync_alias``
ensures the ``domain`` in multisite's ``Alias`` model is updated to match that of django's ``Site`` model. This signal must
run AFTER any ``post-migrate`` signals that manipulate Django's ``Site`` model. If you have an app that manipulates Django's
``Site`` model, place it before ``multisite`` in `settings. INSTALLED_APPS`. If this is not possible, you may configure ``multisite``
to not connect the ``post-migrate`` signal in ``apps.py`` so that you can do it somewhere else in your code.

To configure `multisite` to not connect the `post-post_migrate_sync_alias` in the `apps.py`, update your settings::

    MULTISITE_REGISTER_POST_MIGRATE_SYNC_ALIAS = False

With the `settings` attribute set to `False`, it is your responsibility to connect the signal in your code. Note that if you do not sync the `Alias` and `Site`
models after the `Site` model has changed, multisite may not recognize the domain and switch to the fallback view or
raise a `Http404` error.

Development Environments
------------------------
Multisite returns a valid Alias when in "development mode" (defaulting to the
alias associated with the default SiteID.

Development mode is either:
    - Running tests, i.e. manage.py test
    - Running locally in settings.DEBUG = True, where the hostname is a top-level name, i.e. localhost

In order to have multisite use aliases in local environments, add entries to
your local etc/hosts file to match aliases in your applications.  E.g. ::

    127.0.0.1 example.com
    127.0.0.1 examplealias.com

And access your application at example.com:8000 or examplealias.com:8000 instead of
the usual localhost:8000.

Tests
-----

To run the tests::

    python runtests.py

.. _django-multisite: https://github.com/ecometrica/django-multisite
.. _cross-domain cookies: http://en.wikipedia.org/wiki/HTTP_cookie#Domain_and_Path
.. _Public Suffix List: http://publicsuffix.org/

.. |pypi| image:: https://img.shields.io/pypi/v/django-multisite2.svg
  :target: https://pypi.python.org/pypi/django-multisite2

.. |actions| image:: https://github.com/erikvw/django-multisite2/actions/workflows/build.yml/badge.svg
  :target: https://github.com/erikvw/django-multisite2/actions/workflows/build.yml

.. |codecov| image:: https://codecov.io/gh/erikvw/django-multisite2/branch/develop/graph/badge.svg
  :target: https://codecov.io/gh/erikvw/django-multisite2

.. |downloads| image:: https://pepy.tech/badge/django-multisite2
   :target: https://pepy.tech/project/django-multisite2

.. |maintainability| image:: https://api.codeclimate.com/v1/badges/4992e131641fc6929b1a/maintainability
   :target: https://codeclimate.com/github/erikvw/django-multisite2/maintainability
   :alt: Maintainability

.. |black| image:: https://img.shields.io/badge/code%20style-black-000000.svg
   :target: https://github.com/ambv/black
   :alt: Code Style


            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "django-multisite2",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.12",
    "maintainer_email": "Erik van Widenfelt <ew2789@gmail.com>",
    "keywords": "django, nginx, edc, clinical trials, research, data management, gunicorn, deployment",
    "author": null,
    "author_email": "Leonid S Shestera <leonid@shestera.ru>",
    "download_url": "https://files.pythonhosted.org/packages/c8/c7/b41b822c2c00c585f35070621c0c3527388c9ba85f2c930d82d5917ee28e/django_multisite2-2.1.0.tar.gz",
    "platform": null,
    "description": "|pypi| |actions| |codecov| |downloads| |maintainability| |black|\n\n\n\ndjango_multisite2\n=================\n\nWith ``django_multisite2`` a single instance of a Django project can serve multiple sites using a single settings file (multi-tenant). The current ``SITE_ID`` is extracted from the URL.\n\nIn ``settings``, the static ``SITE_ID`` is replaced with ``django_multisite2`` dynamic ``SiteID``::\n\n    # settings.py\n    SITE_ID = SiteID(default=1)\n\nthe dynamic ``SiteID`` behaves like an integer. When combined with ``django_multisite2`` middleware, ``SiteID`` will return the current ``SITE_ID`` based on the url. For example, each url below is an alias of the same server instance. With ``django_multisite2`` you might have something like this::\n\n    # https://harare.example.com\n    >>> from django.conf import settings\n    >>> settings.SITE_ID\n    10\n\n    # https://kampala.example.com\n    >>> from django.conf import settings\n    >>> settings.SITE_ID\n    20\n\n\nPython 3.11+ Django 4.2+. New releases are cut from the ``main`` branch.\n\nOlder versions of Django are supported by the original `django-multisite`_ project.\n\n\nInstallation\n============\n\nInstall with pip:\n\n.. code-block::\n\n    pip install django-multisite2\n\n\nReplace your ``SITE_ID`` in ``settings.py`` to:\n\n.. code-block::\n\n    from multisite import SiteID\n    SITE_ID = SiteID(default=1)\n\n\nadd to INSTALLED_APPS:\n\n.. code-block::\n\n    INSTALLED_APPS = [\n        ...\n        'django.contrib.sites',\n        'multisite',\n        ...\n    ]\n\n\nEdit settings.py MIDDLEWARE:\n\n.. code-block::\n\n    MIDDLEWARE = (\n        ...\n        'multisite.middleware.DynamicSiteMiddleware',\n        ...\n    )\n\n\nUsing a custom cache\n--------------------\nAppend to settings.py, in order to use a custom cache that can be\nsafely cleared::\n\n    # The cache connection to use for django-multisite.\n    # Default: 'default'\n    CACHE_MULTISITE_ALIAS = 'multisite'\n\n    # The cache key prefix that django-multisite should use.\n    # If not set, defaults to the KEY_PREFIX used in the defined\n    # CACHE_MULTISITE_ALIAS or the default cache (empty string if not set)\n    CACHE_MULTISITE_KEY_PREFIX = ''\n\nIf you have set CACHE\\_MULTISITE\\_ALIAS to a custom value, *e.g.*\n``'multisite'``, add a separate backend to settings.py CACHES::\n\n    CACHES = {\n        'default': {\n            ...\n        },\n        'multisite': {\n            'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',\n            'TIMEOUT': 60 * 60 * 24,  # 24 hours\n            ...\n        },\n    }\n\n\nDomain fallbacks\n----------------\n\nBy default, if the domain name is unknown, multisite will respond with\nan HTTP 404 Not Found error. To change this behaviour, add to\nsettings.py::\n\n    # The view function or class-based view that django-multisite will\n    # use when it cannot match the hostname with a Site. This can be\n    # the name of the function or the function itself.\n    # Default: None\n    MULTISITE_FALLBACK = 'django.views.generic.base.RedirectView\n\n    # Keyword arguments for the MULTISITE_FALLBACK view.\n    # Default: {}\n    MULTISITE_FALLBACK_KWARGS = {'url': 'http://example.com/',\n                                 'permanent': False}\n\nTemplates\n---------\n\nThis feature has been removed in version 2.0.0.\n\nIf required, create template subdirectories for domain level templates (in a\nlocation specified in settings.TEMPLATES['DIRS'].\n\nMultisite's template loader will look for templates in folders with the names of\ndomains, such as::\n\n    templates/example.com\n\n\nThe template loader will also look for templates in a folder specified by the\noptional MULTISITE_DEFAULT_TEMPLATE_DIR setting, e.g.::\n\n    templates/multisite_templates\n\n\nCross-domain cookie support\n---------------------------\n\nIn order to support `cross-domain cookies`_ , for purposes like single-sign-on, prepend the following to the top of\nsettings.py MIDDLEWARE (MIDDLEWARE_CLASSES for Django < 1.10)::\n\n    MIDDLEWARE = (\n        'multisite.middleware.CookieDomainMiddleware',\n        ...\n    )\n\nCookieDomainMiddleware will consult the `Public Suffix List`_\nfor effective top-level domains.\nIt caches this file\nin the system's default temporary directory\nas ``effective_tld_names.dat``.\nTo change this in settings.py::\n\n    MULTISITE_PUBLIC_SUFFIX_LIST_CACHE = '/path/to/multisite_tld.dat'\n\nBy default,\nany cookies without a domain set\nwill be reset to allow \\*.domain.tld.\nTo change this in settings.py::\n\n    MULTISITE_COOKIE_DOMAIN_DEPTH = 1  # Allow only *.subdomain.domain.tld\n\nIn order to fetch a new version of the list,\nrun::\n\n    manage.py update_public_suffix_list\n\n\nPost-migrate signal: post_migrate_sync_alias\n--------------------------------------------\nThe ``post-migrate`` signal ``post_migrate_sync_alias`` is registered in the ``apps.py``. ``post_migrate_sync_alias``\nensures the ``domain`` in multisite's ``Alias`` model is updated to match that of django's ``Site`` model. This signal must\nrun AFTER any ``post-migrate`` signals that manipulate Django's ``Site`` model. If you have an app that manipulates Django's\n``Site`` model, place it before ``multisite`` in `settings. INSTALLED_APPS`. If this is not possible, you may configure ``multisite``\nto not connect the ``post-migrate`` signal in ``apps.py`` so that you can do it somewhere else in your code.\n\nTo configure `multisite` to not connect the `post-post_migrate_sync_alias` in the `apps.py`, update your settings::\n\n    MULTISITE_REGISTER_POST_MIGRATE_SYNC_ALIAS = False\n\nWith the `settings` attribute set to `False`, it is your responsibility to connect the signal in your code. Note that if you do not sync the `Alias` and `Site`\nmodels after the `Site` model has changed, multisite may not recognize the domain and switch to the fallback view or\nraise a `Http404` error.\n\nDevelopment Environments\n------------------------\nMultisite returns a valid Alias when in \"development mode\" (defaulting to the\nalias associated with the default SiteID.\n\nDevelopment mode is either:\n    - Running tests, i.e. manage.py test\n    - Running locally in settings.DEBUG = True, where the hostname is a top-level name, i.e. localhost\n\nIn order to have multisite use aliases in local environments, add entries to\nyour local etc/hosts file to match aliases in your applications.  E.g. ::\n\n    127.0.0.1 example.com\n    127.0.0.1 examplealias.com\n\nAnd access your application at example.com:8000 or examplealias.com:8000 instead of\nthe usual localhost:8000.\n\nTests\n-----\n\nTo run the tests::\n\n    python runtests.py\n\n.. _django-multisite: https://github.com/ecometrica/django-multisite\n.. _cross-domain cookies: http://en.wikipedia.org/wiki/HTTP_cookie#Domain_and_Path\n.. _Public Suffix List: http://publicsuffix.org/\n\n.. |pypi| image:: https://img.shields.io/pypi/v/django-multisite2.svg\n  :target: https://pypi.python.org/pypi/django-multisite2\n\n.. |actions| image:: https://github.com/erikvw/django-multisite2/actions/workflows/build.yml/badge.svg\n  :target: https://github.com/erikvw/django-multisite2/actions/workflows/build.yml\n\n.. |codecov| image:: https://codecov.io/gh/erikvw/django-multisite2/branch/develop/graph/badge.svg\n  :target: https://codecov.io/gh/erikvw/django-multisite2\n\n.. |downloads| image:: https://pepy.tech/badge/django-multisite2\n   :target: https://pepy.tech/project/django-multisite2\n\n.. |maintainability| image:: https://api.codeclimate.com/v1/badges/4992e131641fc6929b1a/maintainability\n   :target: https://codeclimate.com/github/erikvw/django-multisite2/maintainability\n   :alt: Maintainability\n\n.. |black| image:: https://img.shields.io/badge/code%20style-black-000000.svg\n   :target: https://github.com/ambv/black\n   :alt: Code Style\n\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Serve multiple sites from a single Django application",
    "version": "2.1.0",
    "project_urls": {
        "Changelog": "http://github.com/erikvw/django-multisite2/blob/main/CHANGES",
        "Documentation": "http://github.com/erikvw/django-multisite2/blob/develop/README.rst",
        "Homepage": "http://github.com/erikvw/django-multisite2",
        "Repository": "http://github.com/erikvw/django-multisite2.git"
    },
    "split_keywords": [
        "django",
        " nginx",
        " edc",
        " clinical trials",
        " research",
        " data management",
        " gunicorn",
        " deployment"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "010232dda08f37a2955279204a01f3efe8cac69ac0ef298da0eb3eb0c2bfec16",
                "md5": "4cc2c203550ca87151a8a84f45d6fc8d",
                "sha256": "29b63f9ca6aca0f77199f1ef657b1c2a4ccb133ae574aec4f0db5995cc754824"
            },
            "downloads": -1,
            "filename": "django_multisite2-2.1.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "4cc2c203550ca87151a8a84f45d6fc8d",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.12",
            "size": 120810,
            "upload_time": "2025-07-18T21:16:03",
            "upload_time_iso_8601": "2025-07-18T21:16:03.023676Z",
            "url": "https://files.pythonhosted.org/packages/01/02/32dda08f37a2955279204a01f3efe8cac69ac0ef298da0eb3eb0c2bfec16/django_multisite2-2.1.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "c8c7b41b822c2c00c585f35070621c0c3527388c9ba85f2c930d82d5917ee28e",
                "md5": "c20ed2978f5fa593d674270c5a90bf66",
                "sha256": "aeccb6fba824efb28678c2630b2e8223da2b53fff034c0b3f38e9d304921eb97"
            },
            "downloads": -1,
            "filename": "django_multisite2-2.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "c20ed2978f5fa593d674270c5a90bf66",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.12",
            "size": 89545,
            "upload_time": "2025-07-18T21:16:04",
            "upload_time_iso_8601": "2025-07-18T21:16:04.068717Z",
            "url": "https://files.pythonhosted.org/packages/c8/c7/b41b822c2c00c585f35070621c0c3527388c9ba85f2c930d82d5917ee28e/django_multisite2-2.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-18 21:16:04",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "erikvw",
    "github_project": "django-multisite2",
    "travis_ci": false,
    "coveralls": true,
    "github_actions": true,
    "lcname": "django-multisite2"
}
        
Elapsed time: 2.40644s