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.
Files changed (51) hide show
  1. django_multisite2-2.0.0.dist-info/LICENSE +28 -0
  2. django_multisite2-2.0.0.dist-info/METADATA +246 -0
  3. django_multisite2-2.0.0.dist-info/RECORD +51 -0
  4. django_multisite2-2.0.0.dist-info/WHEEL +5 -0
  5. django_multisite2-2.0.0.dist-info/top_level.txt +2 -0
  6. multisite/__init__.py +1 -0
  7. multisite/admin/__init__.py +3 -0
  8. multisite/admin/alias_admin.py +58 -0
  9. multisite/admin/multisite_changelist.py +64 -0
  10. multisite/admin/multisite_model_admin.py +161 -0
  11. multisite/apps.py +29 -0
  12. multisite/exceptions.py +57 -0
  13. multisite/forms.py +22 -0
  14. multisite/hacks.py +163 -0
  15. multisite/management/__init__.py +0 -0
  16. multisite/management/commands/__init__.py +0 -0
  17. multisite/management/commands/update_public_suffix_list.py +33 -0
  18. multisite/middleware/__init__.py +4 -0
  19. multisite/middleware/cookie_domain_middleware.py +72 -0
  20. multisite/middleware/dynamic_site_middleware.py +198 -0
  21. multisite/migrations/0001_initial.py +71 -0
  22. multisite/migrations/0002_alter_alias_id_alter_alias_is_canonical.py +32 -0
  23. multisite/migrations/0003_alter_alias_options_alter_alias_unique_together_and_more.py +41 -0
  24. multisite/migrations/0004_alter_alias_managers.py +22 -0
  25. multisite/migrations/__init__.py +0 -0
  26. multisite/models/__init__.py +3 -0
  27. multisite/models/alias.py +110 -0
  28. multisite/models/managers.py +196 -0
  29. multisite/models/signals.py +36 -0
  30. multisite/models/validators.py +14 -0
  31. multisite/tests/__init__.py +0 -0
  32. multisite/tests/get_test_allowed_hosts.py +14 -0
  33. multisite/tests/get_test_http_response.py +13 -0
  34. multisite/tests/hosts.py +46 -0
  35. multisite/tests/test_settings.py +23 -0
  36. multisite/tests/tests/__init__.py +0 -0
  37. multisite/tests/tests/request_factory.py +12 -0
  38. multisite/tests/tests/test_alias.py +271 -0
  39. multisite/tests/tests/test_contrib_site.py +21 -0
  40. multisite/tests/tests/test_cookie_domain_middleware.py +196 -0
  41. multisite/tests/tests/test_dynamic_site_middleware.py +262 -0
  42. multisite/tests/tests/test_site_cache.py +127 -0
  43. multisite/tests/tests/test_site_domain.py +24 -0
  44. multisite/tests/tests/test_site_id.py +76 -0
  45. multisite/tests/tests/test_template_loader.py +49 -0
  46. multisite/threadlocals.py +136 -0
  47. multisite/utils.py +172 -0
  48. multisite_app/__init__.py +0 -0
  49. multisite_app/apps.py +6 -0
  50. multisite_app/urls.py +5 -0
  51. 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
@@ -0,0 +1,6 @@
1
+ from django.apps import AppConfig as DjangoApponfig
2
+
3
+
4
+ class AppConfig(DjangoApponfig):
5
+ name = "multisite_app"
6
+ verbose_name = "multisite_app"
multisite_app/urls.py ADDED
@@ -0,0 +1,5 @@
1
+ from django.urls import re_path
2
+
3
+ from multisite_app.views import domain_view
4
+
5
+ urlpatterns = [re_path(r"^domain/$", domain_view)]
multisite_app/views.py ADDED
@@ -0,0 +1,8 @@
1
+ from django.http import HttpResponse
2
+
3
+
4
+ def domain_view(request):
5
+ site_id = request.site.id
6
+ domain = request.site.domain
7
+ html = f"<html><body>{site_id}@{domain}</body></html>"
8
+ return HttpResponse(html)