django-multisite2 3.0.0__tar.gz → 3.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/PKG-INFO +10 -11
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/README.rst +9 -10
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/pyproject.toml +1 -1
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/pyproject.toml.orig +1 -1
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/apps.py +1 -1
- django_multisite2-3.1.0/src/multisite/constants.py +2 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/exceptions.py +4 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/middleware/dynamic_site_timezone_middleware.py +8 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/system_checks.py +17 -24
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/utils.py +38 -30
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/LICENSE +0 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/__init__.py +0 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/admin/__init__.py +0 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/admin/alias_admin.py +0 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/admin/multisite_changelist.py +0 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/admin/multisite_model_admin.py +0 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/forms.py +0 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/hacks.py +0 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/management/__init__.py +0 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/management/commands/__init__.py +0 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/management/commands/update_public_suffix_list.py +0 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/middleware/__init__.py +0 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/middleware/cookie_domain_middleware.py +0 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/middleware/dynamic_site_middleware.py +0 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/migrations/0001_initial.py +0 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/migrations/0002_alter_alias_id_alter_alias_is_canonical.py +0 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/migrations/0003_alter_alias_options_alter_alias_unique_together_and_more.py +0 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/migrations/0004_alter_alias_managers.py +0 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/migrations/0005_alter_alias_is_canonical.py +0 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/migrations/__init__.py +0 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/models/__init__.py +0 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/models/alias.py +0 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/models/managers.py +0 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/models/signals.py +0 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/models/validators.py +0 -0
- {django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/threadlocals.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: django-multisite2
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.1.0
|
|
4
4
|
Summary: Serve multiple sites from a single Django application
|
|
5
5
|
Keywords: django,nginx,edc,clinical trials,research,data management,gunicorn,deployment
|
|
6
6
|
Author: Leonid S Shestera
|
|
@@ -303,15 +303,15 @@ Per-site time zones
|
|
|
303
303
|
thread, so Django renders every datetime in local time for whichever site served the
|
|
304
304
|
request. It is the time zone equivalent of what ``SiteID`` does for ``SITE_ID``.
|
|
305
305
|
|
|
306
|
-
Map each site to a time zone in settings.py. Values
|
|
306
|
+
Map each site to a time zone in settings.py. Values must be an IANA key::
|
|
307
307
|
|
|
308
308
|
MULTISITE_TIME_ZONES = {
|
|
309
309
|
1: "Africa/Dar_es_Salaam",
|
|
310
310
|
2: "America/New_York",
|
|
311
311
|
}
|
|
312
312
|
|
|
313
|
-
|
|
314
|
-
|
|
313
|
+
|
|
314
|
+
Add the middleware after ``DynamicSiteMiddleware``
|
|
315
315
|
|
|
316
316
|
.. code-block::
|
|
317
317
|
|
|
@@ -329,11 +329,10 @@ The lookup itself is available directly::
|
|
|
329
329
|
|
|
330
330
|
from multisite.utils import get_multisite_timezone
|
|
331
331
|
|
|
332
|
-
``get_multisite_timezone()`` returns the
|
|
333
|
-
``SITE_ID
|
|
334
|
-
``
|
|
335
|
-
|
|
336
|
-
integer rather than a ``SiteID``.
|
|
332
|
+
``get_multisite_timezone(site_id=None)`` returns the time zone for ``site_id``, or for the
|
|
333
|
+
current ``SITE_ID`` if not given. It requires ``DynamicSiteTimezoneMiddleware`` in
|
|
334
|
+
``MIDDLEWARE`` and raises ``MultisiteTimezoneError`` otherwise, or if ``site_id`` has no
|
|
335
|
+
entry in ``MULTISITE_TIME_ZONES``. The current site falls back to ``settings.TIME_ZONE``.
|
|
337
336
|
|
|
338
337
|
Outside a request, in management commands, signal handlers or queue workers, no time zone
|
|
339
338
|
is activated and Django falls back to ``settings.TIME_ZONE``. Wrap the entry point as you
|
|
@@ -347,8 +346,8 @@ would with ``SiteID.override()``::
|
|
|
347
346
|
Three system checks cover the configuration:
|
|
348
347
|
|
|
349
348
|
* ``multisite.E001`` if ``DynamicSiteTimezoneMiddleware`` is listed before ``DynamicSiteMiddleware``
|
|
350
|
-
* ``multisite.
|
|
351
|
-
* ``multisite.
|
|
349
|
+
* ``multisite.E002`` if the middleware is installed but ``MULTISITE_TIME_ZONES`` is missing or empty
|
|
350
|
+
* ``multisite.E003`` if ``DynamicSiteMiddleware`` is missing altogether
|
|
352
351
|
|
|
353
352
|
|
|
354
353
|
Development Environments
|
|
@@ -275,15 +275,15 @@ Per-site time zones
|
|
|
275
275
|
thread, so Django renders every datetime in local time for whichever site served the
|
|
276
276
|
request. It is the time zone equivalent of what ``SiteID`` does for ``SITE_ID``.
|
|
277
277
|
|
|
278
|
-
Map each site to a time zone in settings.py. Values
|
|
278
|
+
Map each site to a time zone in settings.py. Values must be an IANA key::
|
|
279
279
|
|
|
280
280
|
MULTISITE_TIME_ZONES = {
|
|
281
281
|
1: "Africa/Dar_es_Salaam",
|
|
282
282
|
2: "America/New_York",
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
-
|
|
286
|
-
|
|
285
|
+
|
|
286
|
+
Add the middleware after ``DynamicSiteMiddleware``
|
|
287
287
|
|
|
288
288
|
.. code-block::
|
|
289
289
|
|
|
@@ -301,11 +301,10 @@ The lookup itself is available directly::
|
|
|
301
301
|
|
|
302
302
|
from multisite.utils import get_multisite_timezone
|
|
303
303
|
|
|
304
|
-
``get_multisite_timezone()`` returns the
|
|
305
|
-
``SITE_ID
|
|
306
|
-
``
|
|
307
|
-
|
|
308
|
-
integer rather than a ``SiteID``.
|
|
304
|
+
``get_multisite_timezone(site_id=None)`` returns the time zone for ``site_id``, or for the
|
|
305
|
+
current ``SITE_ID`` if not given. It requires ``DynamicSiteTimezoneMiddleware`` in
|
|
306
|
+
``MIDDLEWARE`` and raises ``MultisiteTimezoneError`` otherwise, or if ``site_id`` has no
|
|
307
|
+
entry in ``MULTISITE_TIME_ZONES``. The current site falls back to ``settings.TIME_ZONE``.
|
|
309
308
|
|
|
310
309
|
Outside a request, in management commands, signal handlers or queue workers, no time zone
|
|
311
310
|
is activated and Django falls back to ``settings.TIME_ZONE``. Wrap the entry point as you
|
|
@@ -319,8 +318,8 @@ would with ``SiteID.override()``::
|
|
|
319
318
|
Three system checks cover the configuration:
|
|
320
319
|
|
|
321
320
|
* ``multisite.E001`` if ``DynamicSiteTimezoneMiddleware`` is listed before ``DynamicSiteMiddleware``
|
|
322
|
-
* ``multisite.
|
|
323
|
-
* ``multisite.
|
|
321
|
+
* ``multisite.E002`` if the middleware is installed but ``MULTISITE_TIME_ZONES`` is missing or empty
|
|
322
|
+
* ``multisite.E003`` if ``DynamicSiteMiddleware`` is missing altogether
|
|
324
323
|
|
|
325
324
|
|
|
326
325
|
Development Environments
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "django-multisite2"
|
|
3
|
-
version = "3.
|
|
3
|
+
version = "3.1.0"
|
|
4
4
|
description = "Serve multiple sites from a single Django application"
|
|
5
5
|
readme = { file = "README.rst", content-type = "text/x-rst" }
|
|
6
6
|
keywords = ["django", "nginx", "edc", "clinical trials", "research", "data management", "gunicorn", "deployment"]
|
|
@@ -27,7 +27,7 @@ class AppConfig(DjangoAppConfig):
|
|
|
27
27
|
|
|
28
28
|
def ready(self):
|
|
29
29
|
register(multisite_middleware_check)
|
|
30
|
-
register(multisite_timezone_setting_check
|
|
30
|
+
register(multisite_timezone_setting_check)
|
|
31
31
|
if not getattr(settings, "MULTISITE_REGISTER_POST_MIGRATE_SYNC_ALIAS", True):
|
|
32
32
|
post_migrate.connect(
|
|
33
33
|
post_migrate_sync_alias,
|
|
@@ -9,6 +9,14 @@ class DynamicSiteTimezoneMiddleware:
|
|
|
9
9
|
Must be listed AFTER `multisite.middleware.DynamicSiteMiddleware`,
|
|
10
10
|
which resolves `settings.SITE_ID` for this request.
|
|
11
11
|
|
|
12
|
+
Requires settings.MULTISITE_TIME_ZONES format {site_id: IANA key}.
|
|
13
|
+
For example:
|
|
14
|
+
MULTISITE_TIME_ZONES = {
|
|
15
|
+
10: "Africa/Gaborone",
|
|
16
|
+
20: "Africa/Dar_es_Salaam",
|
|
17
|
+
30: "Africa/Lagos",
|
|
18
|
+
}
|
|
19
|
+
|
|
12
20
|
Outside a request (management commands, signals, workers) nothing
|
|
13
21
|
is activated and Django falls back to `settings.TIME_ZONE`. Use
|
|
14
22
|
`timezone.override(get_multisite_timezone())` there, as you would use
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from django.conf import settings
|
|
4
|
-
from django.core.checks import CheckMessage, Error
|
|
4
|
+
from django.core.checks import CheckMessage, Error
|
|
5
5
|
|
|
6
|
-
DYNAMIC_SITE_MIDDLEWARE
|
|
7
|
-
DYNAMIC_SITE_TIMEZONE_MIDDLEWARE = "multisite.middleware.DynamicSiteTimezoneMiddleware"
|
|
6
|
+
from .constants import DYNAMIC_SITE_MIDDLEWARE, DYNAMIC_SITE_TIMEZONE_MIDDLEWARE
|
|
8
7
|
|
|
9
8
|
|
|
10
9
|
def multisite_middleware_check(app_configs, **kwargs) -> list[CheckMessage]: # noqa: ARG001
|
|
@@ -22,14 +21,14 @@ def multisite_middleware_check(app_configs, **kwargs) -> list[CheckMessage]: #
|
|
|
22
21
|
return errors
|
|
23
22
|
if DYNAMIC_SITE_MIDDLEWARE not in middleware:
|
|
24
23
|
errors.append(
|
|
25
|
-
|
|
26
|
-
f"Missing MIDDLEWARE. `{DYNAMIC_SITE_TIMEZONE_MIDDLEWARE}`
|
|
27
|
-
f"
|
|
24
|
+
Error(
|
|
25
|
+
f"Missing MIDDLEWARE. `{DYNAMIC_SITE_TIMEZONE_MIDDLEWARE}` "
|
|
26
|
+
f"requires `{DYNAMIC_SITE_MIDDLEWARE}`.",
|
|
28
27
|
hint=(
|
|
29
|
-
"
|
|
30
|
-
"
|
|
28
|
+
f"Add `{DYNAMIC_SITE_MIDDLEWARE}` to settings "
|
|
29
|
+
f"before `{DYNAMIC_SITE_TIMEZONE_MIDDLEWARE}`."
|
|
31
30
|
),
|
|
32
|
-
id="multisite.
|
|
31
|
+
id="multisite.E003",
|
|
33
32
|
)
|
|
34
33
|
)
|
|
35
34
|
elif middleware.index(DYNAMIC_SITE_TIMEZONE_MIDDLEWARE) < middleware.index(
|
|
@@ -50,24 +49,18 @@ def multisite_middleware_check(app_configs, **kwargs) -> list[CheckMessage]: #
|
|
|
50
49
|
|
|
51
50
|
|
|
52
51
|
def multisite_timezone_setting_check(app_configs, **kwargs) -> list[CheckMessage]: # noqa: ARG001
|
|
53
|
-
"""Checks that `settings.MULTISITE_TIME_ZONES`, if set, is acted on.
|
|
54
|
-
|
|
55
|
-
Registered with `deploy=True`, so it runs under `check --deploy`
|
|
56
|
-
and not on every test run.
|
|
57
|
-
"""
|
|
52
|
+
"""Checks that `settings.MULTISITE_TIME_ZONES`, if set, is acted on."""
|
|
58
53
|
errors: list[CheckMessage] = []
|
|
59
|
-
if getattr(settings, "MULTISITE_TIME_ZONES", None) and (
|
|
60
|
-
DYNAMIC_SITE_TIMEZONE_MIDDLEWARE
|
|
61
|
-
not in list(getattr(settings, "MIDDLEWARE", None) or [])
|
|
54
|
+
if not getattr(settings, "MULTISITE_TIME_ZONES", None) and (
|
|
55
|
+
DYNAMIC_SITE_TIMEZONE_MIDDLEWARE in (list(getattr(settings, "MIDDLEWARE", None) or []))
|
|
62
56
|
):
|
|
63
57
|
errors.append(
|
|
64
|
-
|
|
65
|
-
"settings.MULTISITE_TIME_ZONES is
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
id="multisite.W002",
|
|
58
|
+
Error(
|
|
59
|
+
"settings.MULTISITE_TIME_ZONES is missing or not set. "
|
|
60
|
+
f"MULTISITE_TIME_ZONES is required if {DYNAMIC_SITE_TIMEZONE_MIDDLEWARE} "
|
|
61
|
+
"is active in middleware.",
|
|
62
|
+
hint="Add `MULTISITE_TIME_ZONES` to settings.",
|
|
63
|
+
id="multisite.E002",
|
|
71
64
|
)
|
|
72
65
|
)
|
|
73
66
|
return errors
|
|
@@ -15,6 +15,8 @@ from django.core.exceptions import (
|
|
|
15
15
|
from django.http import Http404
|
|
16
16
|
from django.urls import get_callable
|
|
17
17
|
|
|
18
|
+
from .constants import DYNAMIC_SITE_TIMEZONE_MIDDLEWARE
|
|
19
|
+
from .exceptions import MultisiteTimezoneError
|
|
18
20
|
from .threadlocals import SiteID
|
|
19
21
|
|
|
20
22
|
if TYPE_CHECKING:
|
|
@@ -179,35 +181,41 @@ def get_user_sites(request) -> QuerySet[Site]:
|
|
|
179
181
|
return sites
|
|
180
182
|
|
|
181
183
|
|
|
182
|
-
def get_multisite_timezone() -> str:
|
|
183
|
-
"""Returns the IANA key of the time zone for the
|
|
184
|
+
def get_multisite_timezone(site_id: int | None = None) -> str:
|
|
185
|
+
"""Returns the IANA key of the time zone for the given site.
|
|
184
186
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
187
|
+
Requires `DynamicSiteTimezoneMiddleware` and that the given site
|
|
188
|
+
exist in settings.MULTISITE_TIME_ZONES.
|
|
189
|
+
|
|
190
|
+
See also DynamicSiteTimezoneMiddleware and system checks.
|
|
188
191
|
"""
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
192
|
+
|
|
193
|
+
timezone_data: dict[int | str, str] = getattr(settings, "MULTISITE_TIME_ZONES", {})
|
|
194
|
+
if DYNAMIC_SITE_TIMEZONE_MIDDLEWARE not in (
|
|
195
|
+
list(getattr(settings, "MIDDLEWARE", None) or [])
|
|
196
|
+
):
|
|
197
|
+
func_name = sys._getframe().f_code.co_name
|
|
198
|
+
raise MultisiteTimezoneError(
|
|
199
|
+
"Middleware needed for function. "
|
|
200
|
+
f"Add `{DYNAMIC_SITE_TIMEZONE_MIDDLEWARE}` to MIDDLEWARE. "
|
|
201
|
+
f"Got function `{func_name}`."
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
if isinstance(settings.SITE_ID, SiteID) and not timezone_data:
|
|
205
|
+
warnings.warn(
|
|
206
|
+
(
|
|
207
|
+
"settings.MULTISITE_TIME_ZONES not set for multisite deployment. "
|
|
208
|
+
f"Defaulting to {settings.TIME_ZONE}. Try adding MULTISITE_TIME_ZONES "
|
|
209
|
+
"to your settings."
|
|
210
|
+
),
|
|
211
|
+
RuntimeWarning,
|
|
212
|
+
stacklevel=2,
|
|
213
|
+
)
|
|
214
|
+
if site_id is not None and not timezone_data.get(site_id):
|
|
215
|
+
raise MultisiteTimezoneError(
|
|
216
|
+
"settings.MULTISITE_TIME_ZONES missing timezone for site_id. "
|
|
217
|
+
f"Expected one of {timezone_data}. Got site_id={site_id}."
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
site_id: str = settings.SITE_ID if site_id is None else site_id
|
|
221
|
+
return timezone_data.get(site_id) or settings.TIME_ZONE
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/admin/multisite_changelist.py
RENAMED
|
File without changes
|
{django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/admin/multisite_model_admin.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/management/commands/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_multisite2-3.0.0 → django_multisite2-3.1.0}/src/multisite/migrations/0001_initial.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|