Giter Club home page Giter Club logo

django-multisite's Introduction

https://travis-ci.org/ecometrica/django-multisite.svg?branch=master https://coveralls.io/repos/github/ecometrica/django-multisite/badge.svg?branch=master

README

Install with pip:

pip install django-multisite

Or get the code via git:

git clone git://github.com/ecometrica/django-multisite.git django-multisite

Then run:

python setup.py install

Or add the django-multisite/multisite folder to your PYTHONPATH.

If you wish to contribute, instead run:

python setup.py develop

Quickstart

Replace your SITE_ID in settings.py to:

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

Add these to your INSTALLED_APPS:

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

Add to your settings.py TEMPLATES loaders in the OPTIONS section:

TEMPLATES = [
    ...
    {
        ...
        'DIRS': {...}
        'OPTIONS': {
            'loaders': (
                'multisite.template.loaders.filesystem.Loader',
                'django.template.loaders.app_directories.Loader',
            )
        }
        ...
    }
    ...
]

Edit settings.py MIDDLEWARE (MIDDLEWARE_CLASSES for Django < 1.10):

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

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
        ...
    },
}

Multisite determines the ALLOWED_HOSTS by checking all Alias domains. You can also set the MULTISITE_EXTRA_HOSTS to include additional hosts. This can include wildcards.:

MULTISITE_EXTRA_HOSTS = ['example.com']
# will match the single additional host

MULTISITE_EXTRA_HOSTS = ['.example.com']
# will match any host ending '.example.com'

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.

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

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 cookies

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

Tests

To run the tests:

python setup.py test

Or:

pytest

Before deploying a change, to verify it has not broken anything by running:

tox

This runs the tests under every supported combination of Django and Python.

django-multisite's People

Contributors

avbasov avatar brunoprograma avatar chewthemonkey avatar coddingtonbear avatar eddiejessup avatar erikvw avatar jbazik avatar jedie avatar jordanreiter avatar jordiecometrica avatar manos-korakakis avatar mghughes avatar mihalikv avatar pauricthelodger avatar plazix avatar rebkwok avatar rory-geoghegan-ecometrica avatar sfllaw avatar vit-ivanov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-multisite's Issues

Support django 2.0

When #47 is merged, we only need minimal additional changes in order to support django 2.0:

  • fix up foreign key on_delete
  • fix parameters passed to the template loader's get_template_sources method

New PyPi release

Could you please release a new version with support for Django 2.2 on Pypi?

The latest release is over a year old and there have been many updates and fixes to the library.

Doesn't work with django_debug_toolbar

django-multisite does not seem to work with Django debug toolbar

Steps to reproduce:

  1. Install django-debug-toolbar (pip install django-debug-toolbar)
  2. Add debug_toolbar to the INSTALLED_APPS in the project settings
  3. Start the server ..

Result:
The server fails to start without any errors.

general chicken-egg problem

The DynamicSiteMiddleware will always raise 404 if he can't find the current Domain in the Alias model. But i can't login and use the admin panel, if i always get a 404...

Set MULTISITE_FALLBACK will not really help here.

So i have to deactivate DynamicSiteMiddleware, login and insert the current Domain and activate DynamicSiteMiddleware ?!?

Avoid lockout when changing the current site domein

When the current site domein is changed, a developer can lock themselves out of the site. It requires updating the Site and Alias models manually.

Can you add a validator to prevent this from happening?

Template dir for local development

I am appending .local to my domain so that I can develop locally but that means I must change the domain of each site in the database to have .local on the end of it.

This, in turn, means that the template dir that is used is wrong. It is, for example, example.com.local, but the templates are in example.com.

Is there any way around this?

Bump to Django 1.8

Right now setup.py says Django>=1.6. It still works back there---at least, the tests still pass, though I am not totally confident in them---while Django 1.6 and 1.7's docs warn "This document is for an insecure version of Django that is no longer supported. Please upgrade to a newer release!"

Worse, Django 1.6 and 1.7 are simply not supported on python3. I would like to drop support for these by bumping setup.py to Django>=1.8. Django 1.8 is LTS, which means standardizing on it is a safe bet.

Thoughts?

Incorrect cache prefix documentation

Our docs claim that CACHE_MULTISITE_KEY_PREFIX = "" is its default value, but if you actually set that in your settings file this test fails:

======================================================================
FAIL: test_default_key_prefix (multisite.tests.SiteCacheTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/nguenthe/django-multisite/.venv-python2/lib/python2.7/site-packages/django/test/utils.py", line 181, in inner
    return test_func(*args, **kwargs)
  File "/Users/nguenthe/django-multisite/multisite/tests.py", line 447, in test_default_key_prefix
    settings.CACHES['default']['KEY_PREFIX'], self.site.id
AssertionError: u'sites..2' != u'sites.test1.2'
- sites..2
+ sites.test1.2
?       +++++

The code that handles this is tangly and terrible and is literally in a file called "hacks.py":

        if cache is None:
            cache_alias = getattr(settings, 'CACHE_MULTISITE_ALIAS', 'default')
            self._key_prefix = getattr(
                settings,
                'CACHE_MULTISITE_KEY_PREFIX',
                settings.CACHES[cache_alias].get('KEY_PREFIX', '')
            )
            cache = get_cache(cache_alias)
            self._warn_cache_backend(cache, cache_alias)
        else:
            self._key_prefix = getattr(
                settings, 'CACHE_MULTISITE_KEY_PREFIX', cache.key_prefix
            )

It's not clear to me who is wrong here: hacks.py or the documentation of what it's supposed to do. Does anyone have any experience with CACHE_MULTISITE_KEY_PREFIX? What are your thoughts? If there's not much enthusiasm for it I intend to remove it to curtail the convoluted configuration space.

Template loader alters path, can't find template again

Multisite's template loader alters the template path and passes that along to the django template loader. This works great unless some other app decides to cache that path and start over. One such app is nephila/djangocms-blog, which does this:

        selected = select_template(templates)
        return selected.template.name

(https://github.com/nephila/djangocms-blog/blob/develop/djangocms_blog/cms_plugins.py)

Select_template finds and loads the template, so the name passed back is altered by multisite. So, for instance, "home.html" is transformed into "default/home.html" which the multisite loader cannot find.

A simple workaround is to add the django loader to the template loaders. However, multisite's docs suggest that's not necessary.

I think the problem is with multisite, since it is a reasonable expectation that template.name can be reused. But I don't have a simple suggestion for how to fix this.

migration chicken-egg problem

Can't run python manage.py migrate on a fresh database, because multisite.template.loaders.filesystem causes a db query to the django_site table.

Resolve normalized domain names

A domain name can be supplied in a number of ways. I found out, that multisite doesn't account for that. For example domain names example.com and example.com. which refer to the same object do not behave as such.

from multisite.models import Alias
Alias.objects.resolve('example.com')  # Returns <Alias: example.com -> example.com>
Alias.objects.resolve('example.com.')  # Returns None

I suggest to convert the domain name into preferred name syntax, see https://tools.ietf.org/html/rfc1035.html#section-2.3.1, before the domain is actually resolved.

Remove md5

md5 is super deprecated, yet we have it in our code. It isn't being used for anything security-related, but that begs the question of why it is used at all.

From my reading it is being used as a hand-rolled way of writing __hash__(). If that's so, we should gut that and literally use __hash__().

Django 1.10 middleware fails

Facing an issue while adding multisite.middleware.DynamicSiteMiddleware in MIDDLEWARE . I hope need to update the middleware according to django 1.10.

Here is my traceback.

Traceback (most recent call last):
  File "/home/rahul/virtulenv_files/multisite/local/lib/python2.7/site-packages/django/utils/autoreload.py", line 226, in wrapper
    fn(*args, **kwargs)
  File "/home/rahul/virtulenv_files/multisite/local/lib/python2.7/site-packages/django/core/management/commands/runserver.py", line 142, in inner_run
    handler = self.get_handler(*args, **options)
  File "/home/rahul/virtulenv_files/multisite/local/lib/python2.7/site-packages/django/contrib/staticfiles/management/commands/runserver.py", line 27, in get_handler
    handler = super(Command, self).get_handler(*args, **options)
  File "/home/rahul/virtulenv_files/multisite/local/lib/python2.7/site-packages/django/core/management/commands/runserver.py", line 64, in get_handler
    return get_internal_wsgi_application()
  File "/home/rahul/virtulenv_files/multisite/local/lib/python2.7/site-packages/django/core/servers/basehttp.py", line 49, in get_internal_wsgi_application
    return import_string(app_path)
  File "/home/rahul/virtulenv_files/multisite/local/lib/python2.7/site-packages/django/utils/module_loading.py", line 20, in import_string
    module = import_module(module_path)
  File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
    __import__(name)
  File "/home/rahul/Projects/multisite/uniserved_multisite/uniserved_multisite/wsgi.py", line 16, in <module>
    application = get_wsgi_application()
  File "/home/rahul/virtulenv_files/multisite/local/lib/python2.7/site-packages/django/core/wsgi.py", line 14, in get_wsgi_application
    return WSGIHandler()
  File "/home/rahul/virtulenv_files/multisite/local/lib/python2.7/site-packages/django/core/handlers/wsgi.py", line 153, in __init__
    self.load_middleware()
  File "/home/rahul/virtulenv_files/multisite/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 82, in load_middleware
    mw_instance = middleware(handler)
TypeError: __init__() takes exactly 1 argument (2 given)

Ref : https://docs.djangoproject.com/en/1.10/topics/http/middleware/#upgrading-pre-django-1-10-style-middleware

suggest running `black` formatter on code before push

makes it easier to ensure consistent formatting. easier as only code changes, not formatting changes, are show up in a diff. if OK, I'll can prepare a PR after running black, update the README and possibly add a Makefile.

Continuous Integration

In light of #37 and #14, this project could benefit from running a continuous integration server. Over at ecometrica/django-hashedfilenamestorage#4 a kindly soul has even laid out most of the groundwork for integrating these Django projects with Travis-CI and tox---which can replace test_versions by configuring and testing on multiple environments just from a config file.

I look forward to being able to put one of those cute "Build Passing" icons on our README.

KeyError at / 1

I'm getting this errors in production.
For caching we use: redis-cache

Request Method: HEAD

File "/usr/local/lib/python3.5/site-packages/django/contrib/sites/models.py" in get_current
  65.             return self._get_site_by_id(site_id)

File "/usr/local/lib/python3.5/site-packages/django/contrib/sites/models.py" in _get_site_by_id
  37.         return SITE_CACHE[site_id]

File "/usr/local/lib/python3.5/site-packages/multisite/hacks.py" in __getitem__
  124.             raise KeyError(key)

Remove loaders

Our instructions currently say to use TEMPLATES['OPTIONS']['loaders'], but this conflicts with APP_DIRS in Django 1.10:

?: (templates.E001) You have 'APP_DIRS': True in your TEMPLATES but also specify 'loaders' in OPTIONS. Either remove APP_DIRS or remove the 'loaders' option.

We need to update our instructions for Django 1.10 before #37 is really finished. This might require writing something like new backend templates to support APP_DIRS.

(we should probably also make the comment about TEMPLATE_LOADERS on pre-1.8 clearer)

Request for an example

Hi,

I was wondering if you could point me to an complete example go get me going configured with two sites with separate template?

Crash on tldextract==3.0.0

a new version of tldextract came out 20 oct 2020 which removed the cache_file argument in the TLDExtract class

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.