Metadata-Version: 2.1
Name: feincms3-language-sites
Version: 0.0.7
Summary: Multisite support for feincms3
Home-page: https://github.com/matthiask/feincms3-language-sites/
Author: Matthias Kestenholz
Author-email: mk@feinheit.ch
License: BSD-3-Clause
Platform: OS Independent
Classifier: Environment :: Web Environment
Classifier: Framework :: Django
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Topic :: Software Development
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Requires-Python: >=3.8
Description-Content-Type: text/x-rst
Provides-Extra: tests
License-File: LICENSE

=======================
feincms3-language-sites
=======================

.. image:: https://github.com/matthiask/feincms3-language-sites/workflows/Tests/badge.svg
    :target: https://github.com/matthiask/feincms3-language-sites/
    :alt: CI Status

Multisite support for `feincms3 <https://feincms3.readthedocs.io>`_.


Usage scenario
==============

Suppose you have a website with several domains and languages but an exact 1:1
mapping between them. Django offers the ``django.contrib.sites`` application to
partition data but you still have to run one webserver per site.

This app offers a feincms3 abstract page model, a middleware and utilities to
support this scenario. Contrary to `feincms3-sites
<https://github.com/matthiask/feincms3-sites>`__ which is even more flexible
and allows arbitrary combinations of languages and domains this app only allows
exactly one domain per language and exactly one language per domain.


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

* Install the package using ``pip install feincms3-language-sites`` into an
  environment where you're already using feincms3 pages.
* Extend ``feincms3_language_sites.models.AbstractPage`` instead of
  ``feincms3.pages.AbstractPage``. This abstract page already extends
  ``feincms3.mixins.LanguageAndTranslationOfMixin`` so you may remove the
  language mixins (if you have added them before).
* Replace the ``LocaleMiddleware`` with
  ``feincms3_language_sites.middleware.site_middleware``. In case you're using
  feincms3 applications you should ensure that the ``site_middleware`` is added
  before ``feincms3.applications.apps_middleware``.
* Optionally add
  ``feincms3_language_sites.middleware.redirect_to_site_middleware`` if you
  want to enforce the ``host``. The ``SECURE_SSL_REDIRECT`` is also respected.
  The ``redirect_to_site_middleware`` has to be added *before* the
  ``SecurityMiddleware`` otherwise users may get redirected twice in a row.
* Configure the sites.


Configuration
=============

Possible configuration:

.. code-block:: python

    SITES = {
        "de": {
            "host": "127.0.0.1:8000",
            "host_re": r"example\.com$|127.0.0.1:8000$",
        },
        "fr": {
            "host": "localhost:8000",
        },
    }

Sites are checked in the order they are declared (since dictionaries are
guaranteed to preserve the ordering of keys since Python 3.7).

The keys of the ``SITES`` dictionary have to be equal to all language codes in
``LANGUAGES``. The ``host`` is required and should only consist of the host and
an optional port, nothing else. The ``host_re`` is automatically derived from
``host`` if it isn't given explicitly and is matched against
``request.get_host()`` to find the current site. If no ``host_re`` matches the
``site_middleware`` automatically raises a ``DisallowedHost`` exception (which
produces the same error as Django if the request doesn't match
``ALLOWED_HOSTS``).


Utilities
=========

* ``feincms3_language_sites.models.site_for_host``
* ``feincms3_language_sites.models.reverse_language_site_app``


Notes
=====

Note that ``Page.objects.active()`` only returns pages in the current language.
If you want to generate translation links (e.g. using ``...|translations`` in a
template) you do not want to use the ``.active()`` queryset method but build
something yourself which runs ``.filter(is_active=True)``.


