django-multisite2 2.0.0__py3-none-any.whl
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-2.0.0.dist-info/LICENSE +28 -0
- django_multisite2-2.0.0.dist-info/METADATA +246 -0
- django_multisite2-2.0.0.dist-info/RECORD +51 -0
- django_multisite2-2.0.0.dist-info/WHEEL +5 -0
- django_multisite2-2.0.0.dist-info/top_level.txt +2 -0
- multisite/__init__.py +1 -0
- multisite/admin/__init__.py +3 -0
- multisite/admin/alias_admin.py +58 -0
- multisite/admin/multisite_changelist.py +64 -0
- multisite/admin/multisite_model_admin.py +161 -0
- multisite/apps.py +29 -0
- multisite/exceptions.py +57 -0
- multisite/forms.py +22 -0
- multisite/hacks.py +163 -0
- multisite/management/__init__.py +0 -0
- multisite/management/commands/__init__.py +0 -0
- multisite/management/commands/update_public_suffix_list.py +33 -0
- multisite/middleware/__init__.py +4 -0
- multisite/middleware/cookie_domain_middleware.py +72 -0
- multisite/middleware/dynamic_site_middleware.py +198 -0
- multisite/migrations/0001_initial.py +71 -0
- multisite/migrations/0002_alter_alias_id_alter_alias_is_canonical.py +32 -0
- multisite/migrations/0003_alter_alias_options_alter_alias_unique_together_and_more.py +41 -0
- multisite/migrations/0004_alter_alias_managers.py +22 -0
- multisite/migrations/__init__.py +0 -0
- multisite/models/__init__.py +3 -0
- multisite/models/alias.py +110 -0
- multisite/models/managers.py +196 -0
- multisite/models/signals.py +36 -0
- multisite/models/validators.py +14 -0
- multisite/tests/__init__.py +0 -0
- multisite/tests/get_test_allowed_hosts.py +14 -0
- multisite/tests/get_test_http_response.py +13 -0
- multisite/tests/hosts.py +46 -0
- multisite/tests/test_settings.py +23 -0
- multisite/tests/tests/__init__.py +0 -0
- multisite/tests/tests/request_factory.py +12 -0
- multisite/tests/tests/test_alias.py +271 -0
- multisite/tests/tests/test_contrib_site.py +21 -0
- multisite/tests/tests/test_cookie_domain_middleware.py +196 -0
- multisite/tests/tests/test_dynamic_site_middleware.py +262 -0
- multisite/tests/tests/test_site_cache.py +127 -0
- multisite/tests/tests/test_site_domain.py +24 -0
- multisite/tests/tests/test_site_id.py +76 -0
- multisite/tests/tests/test_template_loader.py +49 -0
- multisite/threadlocals.py +136 -0
- multisite/utils.py +172 -0
- multisite_app/__init__.py +0 -0
- multisite_app/apps.py +6 -0
- multisite_app/urls.py +5 -0
- multisite_app/views.py +8 -0
multisite/utils.py
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
from typing import TYPE_CHECKING, Callable
|
|
5
|
+
|
|
6
|
+
from django.apps import apps as django_apps
|
|
7
|
+
from django.conf import settings
|
|
8
|
+
from django.core.exceptions import (
|
|
9
|
+
ImproperlyConfigured,
|
|
10
|
+
MultipleObjectsReturned,
|
|
11
|
+
ObjectDoesNotExist,
|
|
12
|
+
)
|
|
13
|
+
from django.http import Http404
|
|
14
|
+
from django.urls import get_callable
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from django.apps import AppConfig
|
|
18
|
+
from django.contrib.sites.models import Site
|
|
19
|
+
from django.db.models import QuerySet
|
|
20
|
+
|
|
21
|
+
from multisite.models import Alias
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_cache_multisite_alias() -> str:
|
|
25
|
+
return getattr(settings, "CACHE_MULTISITE_ALIAS", "default")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def get_cache_multisite_prefix() -> str | None:
|
|
29
|
+
return getattr(settings, "CACHE_MULTISITE_KEY_PREFIX", None)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get_fallback_view_or_404() -> Callable | Http404:
|
|
33
|
+
fallback = getattr(settings, "MULTISITE_FALLBACK", None)
|
|
34
|
+
if fallback is None:
|
|
35
|
+
raise Http404
|
|
36
|
+
if callable(fallback):
|
|
37
|
+
view = fallback
|
|
38
|
+
else:
|
|
39
|
+
try:
|
|
40
|
+
view = get_callable(fallback)
|
|
41
|
+
except ImportError:
|
|
42
|
+
# newer django forces this to be an error, which is tidier.
|
|
43
|
+
# we rewrite the error to be a bit more helpful to our users.
|
|
44
|
+
raise ImproperlyConfigured(
|
|
45
|
+
"settings.MULTISITE_FALLBACK is not callable: %s" % fallback
|
|
46
|
+
)
|
|
47
|
+
return view
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def get_fallback_kwargs() -> dict | None:
|
|
51
|
+
return getattr(settings, "MULTISITE_FALLBACK_KWARGS", {})
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def sync_canonical_from_site_domain(apps=None, **options):
|
|
55
|
+
"""
|
|
56
|
+
Synchronize canonical Alias objects based on Site.domain.
|
|
57
|
+
|
|
58
|
+
You can pass Q-objects or filter arguments to update a subset of
|
|
59
|
+
Alias objects::
|
|
60
|
+
|
|
61
|
+
Alias.canonical.sync_many(site__domain='example.com')
|
|
62
|
+
|
|
63
|
+
Renamed canonical manager method ``sync_many``.
|
|
64
|
+
|
|
65
|
+
"""
|
|
66
|
+
apps = apps or django_apps
|
|
67
|
+
model_cls = apps.get_model("multisite.alias")
|
|
68
|
+
options.update(is_canonical=1)
|
|
69
|
+
aliases = model_cls.objects.filter(**options)
|
|
70
|
+
for alias in aliases.select_related("site"):
|
|
71
|
+
domain = alias.site.domain
|
|
72
|
+
if domain and alias.domain != domain:
|
|
73
|
+
alias.domain = domain
|
|
74
|
+
alias.save()
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def create_or_sync_missing_canonical_from_site_domain(apps: AppConfig | None = None) -> None:
|
|
78
|
+
"""Create missing canonical Alias objects based on Site.domain.
|
|
79
|
+
|
|
80
|
+
Renamed canonical manager method ``sync_missing``.
|
|
81
|
+
"""
|
|
82
|
+
apps = apps or django_apps
|
|
83
|
+
model_cls = apps.get_model("multisite.alias")
|
|
84
|
+
aliases = model_cls.objects.filter(is_canonical=1)
|
|
85
|
+
try:
|
|
86
|
+
sites = model_cls._meta.get_field("site").remote_field.model
|
|
87
|
+
except AttributeError:
|
|
88
|
+
sites = model_cls._meta.get_field("site").related_model
|
|
89
|
+
for site in sites.objects.exclude(aliases__in=aliases):
|
|
90
|
+
create_or_sync_alias_from_site(site=site, apps=apps)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def create_or_sync_canonical_from_all_sites(
|
|
94
|
+
apps: AppConfig | None = None, verbose: bool | None = None
|
|
95
|
+
) -> None:
|
|
96
|
+
"""Create or sync canonical Alias objects from all Site objects.
|
|
97
|
+
|
|
98
|
+
Renamed canonical manager method ``sync_all``.
|
|
99
|
+
"""
|
|
100
|
+
if verbose:
|
|
101
|
+
sys.stdout.write(" * Syncing canonical from site domain ... \n")
|
|
102
|
+
sync_canonical_from_site_domain(apps=apps)
|
|
103
|
+
if verbose:
|
|
104
|
+
sys.stdout.write(" * Syncing missing canonical from site domain ... \n")
|
|
105
|
+
create_or_sync_missing_canonical_from_site_domain(apps=apps)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def create_or_sync_alias_from_site(
|
|
109
|
+
site: Site = None, force_insert: bool | None = None, apps: AppConfig | None = None
|
|
110
|
+
) -> Alias | None:
|
|
111
|
+
"""Create or synchronize Alias object from ``site``.
|
|
112
|
+
|
|
113
|
+
If `force_insert`, forces creation of Alias object.
|
|
114
|
+
|
|
115
|
+
Renamed model class method ``sync``.
|
|
116
|
+
"""
|
|
117
|
+
alias = None
|
|
118
|
+
apps = apps or django_apps
|
|
119
|
+
force_insert = False if force_insert is None else force_insert
|
|
120
|
+
model_cls = apps.get_model("multisite.alias")
|
|
121
|
+
if domain := site.domain:
|
|
122
|
+
if force_insert:
|
|
123
|
+
alias = model_cls.objects.create(site=site, is_canonical=1, domain=domain)
|
|
124
|
+
else:
|
|
125
|
+
alias, created = model_cls.objects.get_or_create(
|
|
126
|
+
site=site, is_canonical=1, defaults={"domain": domain}
|
|
127
|
+
)
|
|
128
|
+
if not created and alias.domain != domain:
|
|
129
|
+
alias.site = site
|
|
130
|
+
alias.domain = domain
|
|
131
|
+
alias.save()
|
|
132
|
+
else:
|
|
133
|
+
sync_blank_domain(site=site)
|
|
134
|
+
return alias
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def sync_blank_domain(site: Site = None, apps: AppConfig | None = None) -> None:
|
|
138
|
+
"""Delete associated Alias object for ``site``, if domain
|
|
139
|
+
is blank.
|
|
140
|
+
:rtype: object
|
|
141
|
+
"""
|
|
142
|
+
apps = apps or django_apps
|
|
143
|
+
model_cls = apps.get_model("multisite.alias")
|
|
144
|
+
|
|
145
|
+
if site.domain:
|
|
146
|
+
raise ValueError("%r has a domain" % site)
|
|
147
|
+
# Remove canonical Alias, if no non-canonical aliases exist.
|
|
148
|
+
try:
|
|
149
|
+
alias = model_cls.objects.get(site=site)
|
|
150
|
+
except ObjectDoesNotExist:
|
|
151
|
+
# Nothing to delete
|
|
152
|
+
pass
|
|
153
|
+
else:
|
|
154
|
+
if not alias.is_canonical:
|
|
155
|
+
raise MultipleObjectsReturned(
|
|
156
|
+
"Other %s still exist for %r"
|
|
157
|
+
% (model_cls._meta.verbose_name_plural.capitalize(), site)
|
|
158
|
+
)
|
|
159
|
+
alias.delete()
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def get_user_sites(request) -> QuerySet[Site]:
|
|
163
|
+
if request.user.is_superuser:
|
|
164
|
+
sites = Site.objects.all()
|
|
165
|
+
else:
|
|
166
|
+
try:
|
|
167
|
+
user_profile = request.user.userprofile.sites.all()
|
|
168
|
+
except AttributeError:
|
|
169
|
+
sites = Site.objects.all().order_by("domain")
|
|
170
|
+
else:
|
|
171
|
+
sites = user_profile.sites.order_by("domain")
|
|
172
|
+
return sites
|
|
File without changes
|
multisite_app/apps.py
ADDED
multisite_app/urls.py
ADDED