django-multisite2 2.1.1__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 (138) hide show
  1. django_multisite2-2.1.1.dist-info/LICENSE +28 -0
  2. django_multisite2-2.1.1.dist-info/METADATA +244 -0
  3. django_multisite2-2.1.1.dist-info/RECORD +138 -0
  4. django_multisite2-2.1.1.dist-info/WHEEL +5 -0
  5. django_multisite2-2.1.1.dist-info/top_level.txt +2 -0
  6. multisite/__init__.py +2 -0
  7. multisite/__pycache__/__init__.cpython-310.pyc +0 -0
  8. multisite/__pycache__/__init__.cpython-311.pyc +0 -0
  9. multisite/__pycache__/__init__.cpython-312.pyc +0 -0
  10. multisite/__pycache__/__init__.cpython-39.pyc +0 -0
  11. multisite/__pycache__/__version__.cpython-310.pyc +0 -0
  12. multisite/__pycache__/__version__.cpython-311.pyc +0 -0
  13. multisite/__pycache__/__version__.cpython-312.pyc +0 -0
  14. multisite/__pycache__/__version__.cpython-39.pyc +0 -0
  15. multisite/__pycache__/apps.cpython-312.pyc +0 -0
  16. multisite/__pycache__/exceptions.cpython-312.pyc +0 -0
  17. multisite/__pycache__/forms.cpython-310.pyc +0 -0
  18. multisite/__pycache__/forms.cpython-311.pyc +0 -0
  19. multisite/__pycache__/forms.cpython-312.pyc +0 -0
  20. multisite/__pycache__/forms.cpython-39.pyc +0 -0
  21. multisite/__pycache__/hacks.cpython-310.pyc +0 -0
  22. multisite/__pycache__/hacks.cpython-311.pyc +0 -0
  23. multisite/__pycache__/hacks.cpython-312.pyc +0 -0
  24. multisite/__pycache__/hacks.cpython-39.pyc +0 -0
  25. multisite/__pycache__/test_settings.cpython-310-pytest-6.2.5.pyc +0 -0
  26. multisite/__pycache__/test_settings.cpython-311-pytest-8.1.1.pyc +0 -0
  27. multisite/__pycache__/test_settings.cpython-312-pytest-7.4.4.pyc +0 -0
  28. multisite/__pycache__/test_settings.cpython-312-pytest-8.1.1.pyc +0 -0
  29. multisite/__pycache__/test_settings.cpython-39-pytest-6.2.5.pyc +0 -0
  30. multisite/__pycache__/tests.cpython-310-pytest-6.2.5.pyc +0 -0
  31. multisite/__pycache__/tests.cpython-311-pytest-8.1.1.pyc +0 -0
  32. multisite/__pycache__/tests.cpython-312-pytest-7.4.4.pyc +0 -0
  33. multisite/__pycache__/tests.cpython-312-pytest-8.1.1.pyc +0 -0
  34. multisite/__pycache__/tests.cpython-39-pytest-6.2.5.pyc +0 -0
  35. multisite/__pycache__/threadlocals.cpython-310.pyc +0 -0
  36. multisite/__pycache__/threadlocals.cpython-311.pyc +0 -0
  37. multisite/__pycache__/threadlocals.cpython-312.pyc +0 -0
  38. multisite/__pycache__/threadlocals.cpython-39.pyc +0 -0
  39. multisite/__pycache__/utils.cpython-312.pyc +0 -0
  40. multisite/__version__.py +1 -0
  41. multisite/admin/__init__.py +3 -0
  42. multisite/admin/__pycache__/__init__.cpython-312.pyc +0 -0
  43. multisite/admin/__pycache__/alias_admin.cpython-312.pyc +0 -0
  44. multisite/admin/__pycache__/multisite_changelist.cpython-312.pyc +0 -0
  45. multisite/admin/__pycache__/multisite_model_admin.cpython-312.pyc +0 -0
  46. multisite/admin/alias_admin.py +58 -0
  47. multisite/admin/multisite_changelist.py +64 -0
  48. multisite/admin/multisite_model_admin.py +161 -0
  49. multisite/apps.py +29 -0
  50. multisite/exceptions.py +57 -0
  51. multisite/forms.py +22 -0
  52. multisite/hacks.py +163 -0
  53. multisite/management/__init__.py +0 -0
  54. multisite/management/__pycache__/__init__.cpython-310.pyc +0 -0
  55. multisite/management/__pycache__/__init__.cpython-311.pyc +0 -0
  56. multisite/management/__pycache__/__init__.cpython-312.pyc +0 -0
  57. multisite/management/__pycache__/__init__.cpython-39.pyc +0 -0
  58. multisite/management/commands/__init__.py +0 -0
  59. multisite/management/commands/__pycache__/__init__.cpython-310.pyc +0 -0
  60. multisite/management/commands/__pycache__/__init__.cpython-311.pyc +0 -0
  61. multisite/management/commands/__pycache__/__init__.cpython-312.pyc +0 -0
  62. multisite/management/commands/__pycache__/__init__.cpython-39.pyc +0 -0
  63. multisite/management/commands/__pycache__/update_public_suffix_list.cpython-310.pyc +0 -0
  64. multisite/management/commands/__pycache__/update_public_suffix_list.cpython-311.pyc +0 -0
  65. multisite/management/commands/__pycache__/update_public_suffix_list.cpython-312.pyc +0 -0
  66. multisite/management/commands/__pycache__/update_public_suffix_list.cpython-39.pyc +0 -0
  67. multisite/management/commands/update_public_suffix_list.py +33 -0
  68. multisite/middleware/__init__.py +4 -0
  69. multisite/middleware/__pycache__/__init__.cpython-312.pyc +0 -0
  70. multisite/middleware/__pycache__/cookie_domain_middleware.cpython-312.pyc +0 -0
  71. multisite/middleware/__pycache__/dynamic_site_middleware.cpython-312.pyc +0 -0
  72. multisite/middleware/cookie_domain_middleware.py +72 -0
  73. multisite/middleware/dynamic_site_middleware.py +195 -0
  74. multisite/migrations/0001_initial.py +71 -0
  75. multisite/migrations/0002_alter_alias_id_alter_alias_is_canonical.py +32 -0
  76. multisite/migrations/0003_alter_alias_options_alter_alias_unique_together_and_more.py +41 -0
  77. multisite/migrations/__init__.py +0 -0
  78. multisite/migrations/__pycache__/0001_initial.cpython-310.pyc +0 -0
  79. multisite/migrations/__pycache__/0001_initial.cpython-311.pyc +0 -0
  80. multisite/migrations/__pycache__/0001_initial.cpython-312.pyc +0 -0
  81. multisite/migrations/__pycache__/0001_initial.cpython-39.pyc +0 -0
  82. multisite/migrations/__pycache__/0002_alter_alias_id_alter_alias_is_canonical.cpython-310.pyc +0 -0
  83. multisite/migrations/__pycache__/0002_alter_alias_id_alter_alias_is_canonical.cpython-311.pyc +0 -0
  84. multisite/migrations/__pycache__/0002_alter_alias_id_alter_alias_is_canonical.cpython-312.pyc +0 -0
  85. multisite/migrations/__pycache__/0002_alter_alias_id_alter_alias_is_canonical.cpython-39.pyc +0 -0
  86. multisite/migrations/__pycache__/0003_alias_multisite_alias_canon_site_uniq.cpython-311.pyc +0 -0
  87. multisite/migrations/__pycache__/0003_alter_alias_options_alter_alias_unique_together_and_more.cpython-312.pyc +0 -0
  88. multisite/migrations/__pycache__/__init__.cpython-310.pyc +0 -0
  89. multisite/migrations/__pycache__/__init__.cpython-311.pyc +0 -0
  90. multisite/migrations/__pycache__/__init__.cpython-312.pyc +0 -0
  91. multisite/migrations/__pycache__/__init__.cpython-39.pyc +0 -0
  92. multisite/models/__init__.py +3 -0
  93. multisite/models/__pycache__/__init__.cpython-312.pyc +0 -0
  94. multisite/models/__pycache__/alias.cpython-312.pyc +0 -0
  95. multisite/models/__pycache__/managers.cpython-312.pyc +0 -0
  96. multisite/models/__pycache__/signals.cpython-312.pyc +0 -0
  97. multisite/models/__pycache__/validators.cpython-312.pyc +0 -0
  98. multisite/models/alias.py +110 -0
  99. multisite/models/managers.py +196 -0
  100. multisite/models/signals.py +36 -0
  101. multisite/models/validators.py +14 -0
  102. multisite/tests/__init__.py +0 -0
  103. multisite/tests/__pycache__/__init__.cpython-312.pyc +0 -0
  104. multisite/tests/__pycache__/get_test_allowed_hosts.cpython-312.pyc +0 -0
  105. multisite/tests/__pycache__/get_test_http_response.cpython-312.pyc +0 -0
  106. multisite/tests/__pycache__/test_settings.cpython-312-pytest-8.1.1.pyc +0 -0
  107. multisite/tests/__pycache__/test_settings.cpython-312.pyc +0 -0
  108. multisite/tests/__pycache__/tests.cpython-312-pytest-8.1.1.pyc +0 -0
  109. multisite/tests/get_test_allowed_hosts.py +14 -0
  110. multisite/tests/get_test_http_response.py +13 -0
  111. multisite/tests/hosts.py +46 -0
  112. multisite/tests/test_settings.py +23 -0
  113. multisite/tests/tests/__init__.py +0 -0
  114. multisite/tests/tests/__pycache__/__init__.cpython-312.pyc +0 -0
  115. multisite/tests/tests/__pycache__/request_factory.cpython-312.pyc +0 -0
  116. multisite/tests/tests/__pycache__/test_alias.cpython-312.pyc +0 -0
  117. multisite/tests/tests/__pycache__/test_contrib_site.cpython-312.pyc +0 -0
  118. multisite/tests/tests/__pycache__/test_cookie_domain_middleware.cpython-312.pyc +0 -0
  119. multisite/tests/tests/__pycache__/test_dynamic_site_middleware.cpython-312.pyc +0 -0
  120. multisite/tests/tests/__pycache__/test_site_cache.cpython-312.pyc +0 -0
  121. multisite/tests/tests/__pycache__/test_site_domain.cpython-312.pyc +0 -0
  122. multisite/tests/tests/__pycache__/test_site_id.cpython-312.pyc +0 -0
  123. multisite/tests/tests/__pycache__/test_template_loader.cpython-312.pyc +0 -0
  124. multisite/tests/tests/request_factory.py +12 -0
  125. multisite/tests/tests/test_alias.py +272 -0
  126. multisite/tests/tests/test_contrib_site.py +21 -0
  127. multisite/tests/tests/test_cookie_domain_middleware.py +196 -0
  128. multisite/tests/tests/test_dynamic_site_middleware.py +262 -0
  129. multisite/tests/tests/test_site_cache.py +127 -0
  130. multisite/tests/tests/test_site_domain.py +24 -0
  131. multisite/tests/tests/test_site_id.py +76 -0
  132. multisite/tests/tests/test_template_loader.py +49 -0
  133. multisite/threadlocals.py +149 -0
  134. multisite/utils.py +165 -0
  135. multisite_app/__init__.py +0 -0
  136. multisite_app/apps.py +6 -0
  137. multisite_app/urls.py +5 -0
  138. multisite_app/views.py +8 -0
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2023, Ecometrica
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,244 @@
1
+ Metadata-Version: 2.1
2
+ Name: django-multisite2
3
+ Version: 2.1.1
4
+ Summary: Serve multiple sites from a single Django application
5
+ Home-page: http://github.com/erikvw/django-multisite
6
+ Author: Leonid S Shestera
7
+ Author-email: leonid@shestera.ru
8
+ Maintainer: Ecometrica
9
+ Maintainer-email: dev@ecometrica.com
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Web Environment
12
+ Classifier: Framework :: Django
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: BSD License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Internet
20
+ Classifier: Topic :: Internet :: WWW/HTTP
21
+ Classifier: Topic :: Software Development :: Libraries
22
+ Classifier: Topic :: Utilities
23
+ Requires-Python: >=3.11
24
+ Description-Content-Type: text/x-rst
25
+ License-File: LICENSE
26
+ Requires-Dist: tldextract
27
+
28
+ |pypi| |actions| |codecov| |downloads| |maintainability| |black|
29
+
30
+
31
+
32
+ README
33
+ ======
34
+
35
+ Install with pip::
36
+
37
+ pip install django-multisite-edc
38
+
39
+
40
+ Quickstart
41
+ ----------
42
+
43
+ Replace your SITE_ID in settings.py to::
44
+
45
+ from multisite import SiteID
46
+ SITE_ID = SiteID(default=1)
47
+
48
+ Add these to your INSTALLED_APPS::
49
+
50
+ INSTALLED_APPS = [
51
+ ...
52
+ 'django.contrib.sites',
53
+ 'multisite',
54
+ ...
55
+ ]
56
+
57
+ Add to your settings.py TEMPLATES loaders in the OPTIONS section::
58
+
59
+ TEMPLATES = [
60
+ ...
61
+ {
62
+ ...
63
+ 'DIRS': {...}
64
+ 'OPTIONS': {
65
+ 'loaders': (
66
+ 'multisite.template.loaders.filesystem.Loader',
67
+ 'django.template.loaders.app_directories.Loader',
68
+ )
69
+ }
70
+ ...
71
+ }
72
+ ...
73
+ ]
74
+
75
+ Edit settings.py MIDDLEWARE::
76
+
77
+ MIDDLEWARE = (
78
+ ...
79
+ 'multisite.middleware.DynamicSiteMiddleware',
80
+ ...
81
+ )
82
+
83
+ Append to settings.py, in order to use a custom cache that can be
84
+ safely cleared::
85
+
86
+ # The cache connection to use for django-multisite.
87
+ # Default: 'default'
88
+ CACHE_MULTISITE_ALIAS = 'multisite'
89
+
90
+ # The cache key prefix that django-multisite should use.
91
+ # If not set, defaults to the KEY_PREFIX used in the defined
92
+ # CACHE_MULTISITE_ALIAS or the default cache (empty string if not set)
93
+ CACHE_MULTISITE_KEY_PREFIX = ''
94
+
95
+ If you have set CACHE\_MULTISITE\_ALIAS to a custom value, *e.g.*
96
+ ``'multisite'``, add a separate backend to settings.py CACHES::
97
+
98
+ CACHES = {
99
+ 'default': {
100
+ ...
101
+ },
102
+ 'multisite': {
103
+ 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
104
+ 'TIMEOUT': 60 * 60 * 24, # 24 hours
105
+ ...
106
+ },
107
+ }
108
+
109
+ Development Environments
110
+ ------------------------
111
+ Multisite returns a valid Alias when in "development mode" (defaulting to the
112
+ alias associated with the default SiteID.
113
+
114
+ Development mode is either:
115
+ - Running tests, i.e. manage.py test
116
+ - Running locally in settings.DEBUG = True, where the hostname is a top-level name, i.e. localhost
117
+
118
+ In order to have multisite use aliases in local environments, add entries to
119
+ your local etc/hosts file to match aliases in your applications. E.g. ::
120
+
121
+ 127.0.0.1 example.com
122
+ 127.0.0.1 examplealias.com
123
+
124
+ And access your application at example.com:8000 or examplealias.com:8000 instead of
125
+ the usual localhost:8000.
126
+
127
+
128
+ Domain fallbacks
129
+ ----------------
130
+
131
+ By default, if the domain name is unknown, multisite will respond with
132
+ an HTTP 404 Not Found error. To change this behaviour, add to
133
+ settings.py::
134
+
135
+ # The view function or class-based view that django-multisite will
136
+ # use when it cannot match the hostname with a Site. This can be
137
+ # the name of the function or the function itself.
138
+ # Default: None
139
+ MULTISITE_FALLBACK = 'django.views.generic.base.RedirectView
140
+
141
+ # Keyword arguments for the MULTISITE_FALLBACK view.
142
+ # Default: {}
143
+ MULTISITE_FALLBACK_KWARGS = {'url': 'http://example.com/',
144
+ 'permanent': False}
145
+
146
+ Templates
147
+ ---------
148
+ If required, create template subdirectories for domain level templates (in a
149
+ location specified in settings.TEMPLATES['DIRS'].
150
+
151
+ Multisite's template loader will look for templates in folders with the names of
152
+ domains, such as::
153
+
154
+ templates/example.com
155
+
156
+
157
+ The template loader will also look for templates in a folder specified by the
158
+ optional MULTISITE_DEFAULT_TEMPLATE_DIR setting, e.g.::
159
+
160
+ templates/multisite_templates
161
+
162
+
163
+ Cross-domain cookies
164
+ --------------------
165
+
166
+ In order to support `cross-domain cookies`_,
167
+ for purposes like single-sign-on,
168
+ prepend the following to the top of
169
+ settings.py MIDDLEWARE (MIDDLEWARE_CLASSES for Django < 1.10)::
170
+
171
+ MIDDLEWARE = (
172
+ 'multisite.middleware.CookieDomainMiddleware',
173
+ ...
174
+ )
175
+
176
+ CookieDomainMiddleware will consult the `Public Suffix List`_
177
+ for effective top-level domains.
178
+ It caches this file
179
+ in the system's default temporary directory
180
+ as ``effective_tld_names.dat``.
181
+ To change this in settings.py::
182
+
183
+ MULTISITE_PUBLIC_SUFFIX_LIST_CACHE = '/path/to/multisite_tld.dat'
184
+
185
+ By default,
186
+ any cookies without a domain set
187
+ will be reset to allow \*.domain.tld.
188
+ To change this in settings.py::
189
+
190
+ MULTISITE_COOKIE_DOMAIN_DEPTH = 1 # Allow only *.subdomain.domain.tld
191
+
192
+ In order to fetch a new version of the list,
193
+ run::
194
+
195
+ manage.py update_public_suffix_list
196
+
197
+ .. _cross-domain cookies: http://en.wikipedia.org/wiki/HTTP_cookie#Domain_and_Path
198
+ .. _Public Suffix List: http://publicsuffix.org/
199
+
200
+ Post-migrate signal: post_migrate_sync_alias
201
+ --------------------------------------------
202
+ The `post-migrate` signal `post_migrate_sync_alias` is registered in the `apps.py`. `post_migrate_sync_alias`
203
+ ensures the `domain` in multisite's `Alias` model is updated to match that of django's `Site` model. This signal must
204
+ run AFTER any `post-migrate` signals that manipulate Django's `Site` model. If you have an app that manipulates Django's
205
+ `Site` model, place it before `multisite` in `settings. INSTALLED_APPS`. If this is not possible, you may configure `multisite`
206
+ to not connect the `post-migrate` signal in `apps.py` so that you can do it somewhere else in your code.
207
+
208
+ To configure `multisite` to not connect the `post-post_migrate_sync_alias` in the `apps.py`, update your settings::
209
+
210
+ MULTISITE_REGISTER_POST_MIGRATE_SYNC_ALIAS = False
211
+
212
+ With the `settings` attribute set to `False`, it is your responsibility to connect the signal in your code. Note that if you do not sync the `Alias` and `Site`
213
+ models after the `Site` model has changed, multisite may not recognize the domain and switch to the fallback view or
214
+ raise a `Http404` error.
215
+
216
+ Tests
217
+ -----
218
+
219
+ To run the tests::
220
+
221
+ python runtests.py
222
+
223
+
224
+
225
+ .. |pypi| image:: https://img.shields.io/pypi/v/django-multisite.svg
226
+ :target: https://pypi.python.org/pypi/django-multisite
227
+
228
+ .. |actions| image:: https://github.com/erikvw/django-multisite/actions/workflows/build.yml/badge.svg
229
+ :target: https://github.com/erikvw/django-multisite/actions/workflows/build.yml
230
+
231
+ .. |codecov| image:: https://codecov.io/gh/erikvw/django-multisite/branch/develop/graph/badge.svg
232
+ :target: https://codecov.io/gh/erikvw/django-multisite
233
+
234
+ .. |downloads| image:: https://pepy.tech/badge/django-multisite
235
+ :target: https://pepy.tech/project/django-multisite
236
+
237
+ .. |maintainability| image:: https://api.codeclimate.com/v1/badges/d280e92995a883a4f8db/maintainability
238
+ :target: https://codeclimate.com/github/erikvw/django-multisite/maintainability
239
+ :alt: Maintainability
240
+
241
+ .. |black| image:: https://img.shields.io/badge/code%20style-black-000000.svg
242
+ :target: https://github.com/ambv/black
243
+ :alt: Code Style
244
+
@@ -0,0 +1,138 @@
1
+ multisite/__init__.py,sha256=rgkTJOm7Cl-3L8QvHrQ9DuLeq4PimWSjZgW_w45EJK8,82
2
+ multisite/__version__.py,sha256=_7OlQdbVkK4jad0CLdpI0grT-zEAb-qgFmH5mFzDXiA,22
3
+ multisite/apps.py,sha256=K69kWIqoWaZfbhlLVSxfYLQd-AhojiLxxXmjd26ljbo,975
4
+ multisite/exceptions.py,sha256=FwsrZfie71gUjiOlvDO9NYX8X58P1fTagfU-VBQ3qb8,1317
5
+ multisite/forms.py,sha256=LKojjbDvy3Lfu1-Tgjt4XKuJBYLkYOTBa4oRUJ12-dg,681
6
+ multisite/hacks.py,sha256=OZk7adtXOV37gzi8XETHMGr-cVVZkNbcWsAQrJT3h0E,5171
7
+ multisite/threadlocals.py,sha256=nEx68V5X23_AIurLt5GnjcaiwRUD4qg2FarxHb78LQ4,4447
8
+ multisite/utils.py,sha256=EPIrH-suHC0quevnH1AjVLYtbQ4dcoVaUep8kGngRGc,5302
9
+ multisite/__pycache__/__init__.cpython-310.pyc,sha256=o-KE25iJEcPLh7oHyCS9-jMdsfNtPFh7M_OXqeZ0U3U,261
10
+ multisite/__pycache__/__init__.cpython-311.pyc,sha256=3KYerIER-Yj9BoG1VmDvALtxk65bkdwsfa_rLuCt_bU,313
11
+ multisite/__pycache__/__init__.cpython-312.pyc,sha256=pCZQiKgvxqIfhg9r13WWJps7bEAF0UAjPJMsnZtB4VI,272
12
+ multisite/__pycache__/__init__.cpython-39.pyc,sha256=o0B0coI_IaYcWIv-C6R0IWn0QYWvcrCVTGjvXYsN6b8,259
13
+ multisite/__pycache__/__version__.cpython-310.pyc,sha256=DP2zEqX3h-OgMADuI8en7ddJjbUIOv9Cpl0IrJqiOaM,187
14
+ multisite/__pycache__/__version__.cpython-311.pyc,sha256=_8ozhNABPUqn7fF5bGTx1MQ2aPhFke95GKe_s9Q1sOI,202
15
+ multisite/__pycache__/__version__.cpython-312.pyc,sha256=5t7V-LcXOaJcGRCAyto2Rt5JN0w0s7kbZHOd8AgYqwg,196
16
+ multisite/__pycache__/__version__.cpython-39.pyc,sha256=sM4Z2arFQjXREYZV4oLsivh16Ge7C5yf7PqWLAj3jjo,185
17
+ multisite/__pycache__/apps.cpython-312.pyc,sha256=cyy0mYttUUMTJKuVyFq7bK_OELcXTFitW_WBzs-Eq-A,1629
18
+ multisite/__pycache__/exceptions.cpython-312.pyc,sha256=7Y25K5Bsn2Daug3SGeLnNKtjJt6eYfqXDzridM8U_Jc,2660
19
+ multisite/__pycache__/forms.cpython-310.pyc,sha256=Z1yiE-5riIgcOm8mAKeSdbBLeT5duk0CDVRAsx_tkWw,975
20
+ multisite/__pycache__/forms.cpython-311.pyc,sha256=UCjR6rVpHgEtsBmqhsbI5NLR92WG3UvZxUf4Dntlqq8,1349
21
+ multisite/__pycache__/forms.cpython-312.pyc,sha256=AFi0wgkjGspOLJ3Kj_o-HUjQ78fxu5kI-yTIvrxoP_U,1342
22
+ multisite/__pycache__/forms.cpython-39.pyc,sha256=O5L4Dtrt3q72LyWPlG594rLoD8d0OKMLpCvOP25j0bg,973
23
+ multisite/__pycache__/hacks.cpython-310.pyc,sha256=-XnDc_5CH2uGGTYyOcom9q-hzUa3So-2ccb8TLMM3ag,5419
24
+ multisite/__pycache__/hacks.cpython-311.pyc,sha256=PuNAPVxrSKFwZ5zgCuwNCf9b4cbHGIgbZHEusl_3zR4,8284
25
+ multisite/__pycache__/hacks.cpython-312.pyc,sha256=VFvs5z3mcsPP4un_NoxDqfeiIGKPR0ZElunUIGWyTYA,8496
26
+ multisite/__pycache__/hacks.cpython-39.pyc,sha256=xTTXkNjYOuhH_xHkThHZ--B3fP6rBYjyv5VM5SKkwq8,5443
27
+ multisite/__pycache__/test_settings.cpython-310-pytest-6.2.5.pyc,sha256=vWryf3wZ8kyjLMFNdHqnVQgNyg3p6zAowutaIn4BPGg,787
28
+ multisite/__pycache__/test_settings.cpython-311-pytest-8.1.1.pyc,sha256=BTKSR5TPLu4YXrbgkW5FdnA8mzBhh4OmN3rNRhU1iGI,979
29
+ multisite/__pycache__/test_settings.cpython-312-pytest-7.4.4.pyc,sha256=jdzgMLTzc72bnTZwS8hsgN5X1LVwxpJc_ypGK7az_4w,755
30
+ multisite/__pycache__/test_settings.cpython-312-pytest-8.1.1.pyc,sha256=G5kSgqYbe0gA8UUU8OFZOsSIAqkVxHgro20fasAqSJU,815
31
+ multisite/__pycache__/test_settings.cpython-39-pytest-6.2.5.pyc,sha256=-QI6i5f6_y7C8GI4zZff2qmRhqWk5g22ecz3OzgwaUE,785
32
+ multisite/__pycache__/tests.cpython-310-pytest-6.2.5.pyc,sha256=ZPRQJaVT5YOGot047SHXRknraiVT7ZMKEAnbnxN7D_w,34639
33
+ multisite/__pycache__/tests.cpython-311-pytest-8.1.1.pyc,sha256=StV4ffrya0knHQgsOj-c8EvOs_jJ6idU0sd1Or5HwWM,82428
34
+ multisite/__pycache__/tests.cpython-312-pytest-7.4.4.pyc,sha256=k5FxPD2uH5HLebmtDOo-FJl9vWoqttRmTyDc7T6yrOE,73963
35
+ multisite/__pycache__/tests.cpython-312-pytest-8.1.1.pyc,sha256=PQgiMH1iKSiI4QF2EQVzmwwqoMvIk_3vmOny6S2BBxQ,74146
36
+ multisite/__pycache__/tests.cpython-39-pytest-6.2.5.pyc,sha256=7WCPfUv3Li0SH3irTlnpqRTS-AA0utwN8-kyzEXy7Q0,35173
37
+ multisite/__pycache__/threadlocals.cpython-310.pyc,sha256=JJAaZbn3BV7rtwqOUK64OKQtWTFoxRwhTaqFwl5aJRc,5094
38
+ multisite/__pycache__/threadlocals.cpython-311.pyc,sha256=wny3rl29db9xklsWc712zrZ7NxNWuE7iUMfcM2_hCqQ,7843
39
+ multisite/__pycache__/threadlocals.cpython-312.pyc,sha256=bqG3psOekUr9MWnZVQChXiqrRlxwlQVViVPNpFpFzVQ,6297
40
+ multisite/__pycache__/threadlocals.cpython-39.pyc,sha256=PHy2RLbyWFsvXe5U87fK_8I5tgw8mLfEo1JhZvIINCY,5446
41
+ multisite/__pycache__/utils.cpython-312.pyc,sha256=AwA6WcdjYN1pGg-iYv3f73287Vmp-ULQA0538dRglYk,7316
42
+ multisite/admin/__init__.py,sha256=ySKx0DadaIOLct0obZeMG5ADQkMR6Scg2bMdXYTf9kc,145
43
+ multisite/admin/alias_admin.py,sha256=gL_1yrRN8otAijdTaK4WyJSeO40ZC3QD5PU-F818Fpk,1706
44
+ multisite/admin/multisite_changelist.py,sha256=PViIYIQ6GLL5D_HbDxTqUJt3TBImc5uYo-8MS_sIWFM,2376
45
+ multisite/admin/multisite_model_admin.py,sha256=2_p-M3jeTLmRlLR3D8KjQaBx_FB6CJWl_ZQdn0RT0bM,6414
46
+ multisite/admin/__pycache__/__init__.cpython-312.pyc,sha256=3WYEPZ3CnrOEaxUYpSdG3MV7TH6GYpuq3ID8NdwxNz8,353
47
+ multisite/admin/__pycache__/alias_admin.cpython-312.pyc,sha256=j-wA1fQUCf49UYgK-AzUPn1fdHq8TRpxgPcvAQhtdzY,2862
48
+ multisite/admin/__pycache__/multisite_changelist.cpython-312.pyc,sha256=2Pc5mL_YqTq_O4QmRKTsJH4bQa_V66_Ifddh_O-EpJU,3415
49
+ multisite/admin/__pycache__/multisite_model_admin.cpython-312.pyc,sha256=J8o66z24ROM5YB5JzuTSO41cIGiSqd_pRp_wKPW0om4,8508
50
+ multisite/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
+ multisite/management/__pycache__/__init__.cpython-310.pyc,sha256=6ZIAnH6ndKpBXEF0zEigKWrjRKlI-l4uPu0qXFliMe4,174
52
+ multisite/management/__pycache__/__init__.cpython-311.pyc,sha256=kSTnCQFOP2oGoQuvXIe9rOs_Jsr0aCDa_N6oUry98e4,190
53
+ multisite/management/__pycache__/__init__.cpython-312.pyc,sha256=epRvJSGtiXgMlePniKO1lE9NpQvWzlwBMwxF7Oezaog,178
54
+ multisite/management/__pycache__/__init__.cpython-39.pyc,sha256=GrOd0Br2DzIKB5dvm_dA0_rKbiVAnNr5_XVDb4YTFb8,172
55
+ multisite/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
+ multisite/management/commands/update_public_suffix_list.py,sha256=lu5zhgE2TgzsjpUT1AHPYV4UxSW68MsVcSmQCtx3-U0,974
57
+ multisite/management/commands/__pycache__/__init__.cpython-310.pyc,sha256=WnWogtpOIAWE5I2t4mAOLAagI6cLKzBxfTY3n1Ygn84,183
58
+ multisite/management/commands/__pycache__/__init__.cpython-311.pyc,sha256=AoiZs1cyWkb3yrNrZ3feEgrMXiryamjSm7XkbgQy2wo,199
59
+ multisite/management/commands/__pycache__/__init__.cpython-312.pyc,sha256=fI55wBjOOxVpr8KfjpYkuOglhaf5gURl_CTnyLO5Yz0,187
60
+ multisite/management/commands/__pycache__/__init__.cpython-39.pyc,sha256=cdcAi4rdPLvbnAjKmeI5HfesajJGcU7RYoehDUP3sCs,181
61
+ multisite/management/commands/__pycache__/update_public_suffix_list.cpython-310.pyc,sha256=dBKX42CcFji2bpxW-w_YXLv7bait6CMcB-KMFoWZFWM,1540
62
+ multisite/management/commands/__pycache__/update_public_suffix_list.cpython-311.pyc,sha256=jG453gMMjpK7S0y8ceOfHf26LrVXMDnTV36bi7OMQeo,2387
63
+ multisite/management/commands/__pycache__/update_public_suffix_list.cpython-312.pyc,sha256=_vlX7rSAmxyIDmLnQM110oayRsUPZsGU49N2JBEdjIA,2091
64
+ multisite/management/commands/__pycache__/update_public_suffix_list.cpython-39.pyc,sha256=vuQZ-KoLjeRO-vsbXDAMkLhycBnOkZ5TNZW1xZKPxFs,1530
65
+ multisite/middleware/__init__.py,sha256=77fFnj0H7FC-S81b62YfZMAfMPU4yKVp0JHmR0or6wk,183
66
+ multisite/middleware/cookie_domain_middleware.py,sha256=dan8R8A-lUJuO-9me86pJH1LJ4e9gxBS4yvzDXiYD1g,2358
67
+ multisite/middleware/dynamic_site_middleware.py,sha256=UInSXorD19R7esnHp5JgsQlCtMbTGzxSFYZeu28gA7I,7466
68
+ multisite/middleware/__pycache__/__init__.cpython-312.pyc,sha256=vwbEyHvhTCEkKvE72cXzw5VkFShlnwhsz6vPINRz5BI,360
69
+ multisite/middleware/__pycache__/cookie_domain_middleware.cpython-312.pyc,sha256=bP1aCGxGKyUwAwnXKbvpVd5v5yPBaA722Jx5HUi5HyQ,3568
70
+ multisite/middleware/__pycache__/dynamic_site_middleware.cpython-312.pyc,sha256=9hRi-lSUC4xVzj3cPkRlBG0VH7DXvmX1YNkpLh_Kz4Q,10062
71
+ multisite/migrations/0001_initial.py,sha256=TaASQ-9L_eIRlAa8dmsT6Z1nbBih2wah2abq4C39Yrc,2273
72
+ multisite/migrations/0002_alter_alias_id_alter_alias_is_canonical.py,sha256=V1Nc2K7nn8hwN8VdkgtUpwuU7z1lSajaPvhsuLLHvfk,911
73
+ multisite/migrations/0003_alter_alias_options_alter_alias_unique_together_and_more.py,sha256=SByQOusXLdf3xaeYIUuhJ5fkXlWqxAvS-WgqQL1n38s,1252
74
+ multisite/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
+ multisite/migrations/__pycache__/0001_initial.cpython-310.pyc,sha256=1B6Vwc6mzQJltrydyxA5W0GzqG6nqJmTDfmQYnZaHi8,1468
76
+ multisite/migrations/__pycache__/0001_initial.cpython-311.pyc,sha256=Az80lYBJbbUugRJrU6f9iRIDiHqnEpQSSet1e46llyY,2107
77
+ multisite/migrations/__pycache__/0001_initial.cpython-312.pyc,sha256=1k36vjNNJMRayco_Vh2yHA4HlJ-QhJXN97n1JVsAPgI,2044
78
+ multisite/migrations/__pycache__/0001_initial.cpython-39.pyc,sha256=_Xuw1EPl8vxecdqU3YxQUanEpIxa3KqI1avt_i8fj9E,1464
79
+ multisite/migrations/__pycache__/0002_alter_alias_id_alter_alias_is_canonical.cpython-310.pyc,sha256=WsRL-lS7X2sScli_slyFnzOcpA7vgsB_CO-ugsma_h4,917
80
+ multisite/migrations/__pycache__/0002_alter_alias_id_alter_alias_is_canonical.cpython-311.pyc,sha256=rZbWWvrmpbelNUje2LDcqqyZmgGfClNpLOpAU5_o8zs,1284
81
+ multisite/migrations/__pycache__/0002_alter_alias_id_alter_alias_is_canonical.cpython-312.pyc,sha256=WFPTqICT4nFvKGrmK-FfFgKKVRvWdEbn7S87eUwxVZY,1250
82
+ multisite/migrations/__pycache__/0002_alter_alias_id_alter_alias_is_canonical.cpython-39.pyc,sha256=oG32JXgecOC4o-ZRVNaAvO37efQf7O04zWConJJ-dWU,913
83
+ multisite/migrations/__pycache__/0003_alias_multisite_alias_canon_site_uniq.cpython-311.pyc,sha256=eCo0_PxFxQheQr7U70FZnbjDLC1-Y6ByEwh_ZNESZHY,931
84
+ multisite/migrations/__pycache__/0003_alter_alias_options_alter_alias_unique_together_and_more.cpython-312.pyc,sha256=uM4NL_JvDkFedgP05MEJ7WroHR08QQL_XwOroGehU-M,1621
85
+ multisite/migrations/__pycache__/__init__.cpython-310.pyc,sha256=almepdhdvYf9kQip_wL-VBt2U1ceZg0TU6kMlbMLCe8,174
86
+ multisite/migrations/__pycache__/__init__.cpython-311.pyc,sha256=X_1mG3DXbtobwRGLmA7nVe9X2XAjaI5-W_Uh8pfLhVQ,190
87
+ multisite/migrations/__pycache__/__init__.cpython-312.pyc,sha256=fj3digPtjW7A-J66XtJrBkOz_oAMUtCJ-pnRIbxa13Q,178
88
+ multisite/migrations/__pycache__/__init__.cpython-39.pyc,sha256=4mNXQWgFwWBQjtsEtS19JJvN13TEk0SBvx0Gkd4Z90M,172
89
+ multisite/models/__init__.py,sha256=bDgmZZANxdN9-x_VjeHKvp6xOsAjJ4Ex9iv4OIKzmQg,165
90
+ multisite/models/alias.py,sha256=xVWGKCxWBCuC52paOeS8QoZqy0PzYfLIKezH4cn3xng,3692
91
+ multisite/models/managers.py,sha256=dBhWrzl7U6XH26_br5BKPi8jxCCCaWQaQDWPXZPPSzo,6929
92
+ multisite/models/signals.py,sha256=LghEu50Vc2PlLBHecMoKO0qhJ62cetMk0RfdnZ3-G1U,1540
93
+ multisite/models/validators.py,sha256=Cq4fkmrQG4rlTDaWCjcmt_me6qRsPlxv3G2y5O79i1U,380
94
+ multisite/models/__pycache__/__init__.cpython-312.pyc,sha256=MxfJvjgD-OOqOqxsL4c3XvQbSZjknWlznFU-Bb_9-nI,395
95
+ multisite/models/__pycache__/alias.cpython-312.pyc,sha256=mxiFtcvsx0bdCIniwkPUKNVo6Jf3ou2b0qLsAlkoKC4,5464
96
+ multisite/models/__pycache__/managers.cpython-312.pyc,sha256=8U3Uxj0B-bTUV7d1DmOckbhvKnUnw6vfkffg_IRMZKE,9759
97
+ multisite/models/__pycache__/signals.cpython-312.pyc,sha256=fC9bj7M9sYIAO4cAw0N1Otah4QVCa4RIL51XaJ-VseI,1937
98
+ multisite/models/__pycache__/validators.cpython-312.pyc,sha256=E59eHJ2pn6kBwYdfJblcjtDV0ZROiyjIcWqXxxSvL9o,720
99
+ multisite/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
100
+ multisite/tests/get_test_allowed_hosts.py,sha256=lXcVJVbr37dmTKo3ajNYoqvDXw_G-JNWcP5iO-lmJgo,400
101
+ multisite/tests/get_test_http_response.py,sha256=qDFqBLULpFjZ5D_MeAOzzW29UD9QEEFiYpNGJocnGKk,329
102
+ multisite/tests/hosts.py,sha256=YXgD6VHu5SNGHVCkY8hQPy0YDSgE98rz5x12D5IVpWo,1212
103
+ multisite/tests/test_settings.py,sha256=PaMu9ZaySI8X0AQQxDCvaYIbTLCo8TRtVDkn9vwc3Q8,575
104
+ multisite/tests/__pycache__/__init__.cpython-312.pyc,sha256=dF9u0a7T4zmIUamvKbrFW_y5TBnWrVjkglM7z-7iiKg,173
105
+ multisite/tests/__pycache__/get_test_allowed_hosts.cpython-312.pyc,sha256=1hfu4daI_63rBvykII3xRTy6KzQw136hs_nzs7OPQyM,563
106
+ multisite/tests/__pycache__/get_test_http_response.cpython-312.pyc,sha256=GSC8xz7bs-Nkzu5LzFsmmwxGzOTwJg9q3PKg4SbaVhs,799
107
+ multisite/tests/__pycache__/test_settings.cpython-312-pytest-8.1.1.pyc,sha256=m5wc6ZC20x3nyLlVn4nV2uYiXJTi-LTdW-VSU-te5rs,830
108
+ multisite/tests/__pycache__/test_settings.cpython-312.pyc,sha256=-aKLysJDRTikXoUHSVTd3GdHBcReo4swplsLsHbstWo,711
109
+ multisite/tests/__pycache__/tests.cpython-312-pytest-8.1.1.pyc,sha256=JsdnluSX5dLj0h3EbEw3PDLI9R5WDScyFaSZlkmssdE,74181
110
+ multisite/tests/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
111
+ multisite/tests/tests/request_factory.py,sha256=8pYWNc4ImtZU-GnMHnj2TzO0PByGrjDyYpZ3bBe8YfU,381
112
+ multisite/tests/tests/test_alias.py,sha256=Rc3sPiE8S0tsbxI74jVOaaz7F6H1sxMggLowX8nnxRg,10558
113
+ multisite/tests/tests/test_contrib_site.py,sha256=jbVWfynr--_azY257ZMQWefukQF5RR0zJ-JgHOxgB28,638
114
+ multisite/tests/tests/test_cookie_domain_middleware.py,sha256=4fqABR6ZMApJ4sUdjK0Y3j8-E6smowURMogVHthWZW4,9193
115
+ multisite/tests/tests/test_dynamic_site_middleware.py,sha256=vweXWXP8vRJe5d_F4b2ujhvF6iX8IUs4qpcqvX-tOsU,10931
116
+ multisite/tests/tests/test_site_cache.py,sha256=0ImbJj7_cSftfbCOGvhllLjB3--QuQB3LtxtX2miOsM,5139
117
+ multisite/tests/tests/test_site_domain.py,sha256=5bdJSEbuzJSeVmoI92NGeHEFJgwCIfDwppJj_HRA25E,923
118
+ multisite/tests/tests/test_site_id.py,sha256=PS3FqC2scTExOqn-pxVXwKjwrfuu5I7CE4Y3r1zQp6g,2889
119
+ multisite/tests/tests/test_template_loader.py,sha256=ydlM3wTpUV1_r8__Su9kGacLYHLzHPY7JMjhKNb51BA,1798
120
+ multisite/tests/tests/__pycache__/__init__.cpython-312.pyc,sha256=TRY9Z4QXurTPNaxYSzpXyMWB93j3aOQp9WK7t4lUS5A,179
121
+ multisite/tests/tests/__pycache__/request_factory.cpython-312.pyc,sha256=w9k75Sx_YG9L4Fn0TkxcsdFSB5ppywlLRcmEvAmUH_8,1005
122
+ multisite/tests/tests/__pycache__/test_alias.cpython-312.pyc,sha256=H7HrKBZ99aHYlncEo63f5XQYntd1f7dSIROQNe5PcrQ,15558
123
+ multisite/tests/tests/__pycache__/test_contrib_site.cpython-312.pyc,sha256=41g0SdG2JldH4LcDhg7GM1FYcJd350KALhtMSvi4cRE,1719
124
+ multisite/tests/tests/__pycache__/test_cookie_domain_middleware.cpython-312.pyc,sha256=P0XTHeeovKsYgeHDw7rl3V7JuOeGiWPZS2Y9VNioXQo,12539
125
+ multisite/tests/tests/__pycache__/test_dynamic_site_middleware.cpython-312.pyc,sha256=BtKvCHSLZOr2qdUadZJC2vTPkNPIvsDJVWbYVBatliY,18989
126
+ multisite/tests/tests/__pycache__/test_site_cache.cpython-312.pyc,sha256=Fgi0KrzmNpnc97atVPDS5ujxzoYnRTvSrAoAP6vHz5U,10180
127
+ multisite/tests/tests/__pycache__/test_site_domain.cpython-312.pyc,sha256=-tp43fbYsDDrskkfwmfEDWi82eZplaXykDu1LkCHMzA,2200
128
+ multisite/tests/tests/__pycache__/test_site_id.cpython-312.pyc,sha256=b975s5C7Nq3uDaykNFy4odly3SBpBwZHdSsrB77Icc4,7151
129
+ multisite/tests/tests/__pycache__/test_template_loader.cpython-312.pyc,sha256=7tlXdDlEiUGuxj_mmYQfJvi4ggOBXoBChKKbC0iWHQg,3635
130
+ multisite_app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
131
+ multisite_app/apps.py,sha256=Wtzh0ZFzebAdpxwSfZIjwDoOV_QB_9HrYimscmtZDo4,149
132
+ multisite_app/urls.py,sha256=C3OZY9b3XjMuunawaMLVsRKRKHYFROZm94JVx1NFR6Q,129
133
+ multisite_app/views.py,sha256=zGs26VicVANJm3HGjZ9Z4TvrWSn2V-f-FXr2AwVQRzY,217
134
+ django_multisite2-2.1.1.dist-info/LICENSE,sha256=ZYRfLPXzj_EygRXJSr99HR6EQuo2UmYHjYjC9YECitE,1497
135
+ django_multisite2-2.1.1.dist-info/METADATA,sha256=pigNGaNsF9yM5IOUUr4I8-4uoHJb7UT37AedIkjEF4M,7706
136
+ django_multisite2-2.1.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
137
+ django_multisite2-2.1.1.dist-info/top_level.txt,sha256=7Kbmk1LiZaUMQBzaIITFXoAQKQLFaA0YaulQ7obUTMM,24
138
+ django_multisite2-2.1.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.43.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ multisite
2
+ multisite_app
multisite/__init__.py ADDED
@@ -0,0 +1,2 @@
1
+ from .__version__ import __version__
2
+ from .threadlocals import SiteDomain, SiteID
@@ -0,0 +1 @@
1
+ __version__ = "2.0.0"
@@ -0,0 +1,3 @@
1
+ from .alias_admin import AliasAdmin
2
+ from .multisite_changelist import MultisiteChangeList
3
+ from .multisite_model_admin import MultisiteModelAdmin
@@ -0,0 +1,58 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from django.contrib import admin
6
+ from django.contrib.sites.admin import SiteAdmin
7
+ from django.contrib.sites.models import Site
8
+ from django.db import models
9
+
10
+ from ..forms import SiteForm
11
+ from ..models import Alias
12
+
13
+ if TYPE_CHECKING:
14
+ from django.contrib.auth.models import User
15
+ from django.core.handlers.wsgi import WSGIRequest as BaseWSGIRequest
16
+ from django.db.models import QuerySet
17
+
18
+ class UserProfile(models.Model):
19
+ user = models.ForeignKey(User, on_delete=models.PROTECT)
20
+ sites = models.ManyToManyField(Site, blank=True)
21
+
22
+ class WSGIRequest(BaseWSGIRequest):
23
+ user: User
24
+
25
+
26
+ @admin.register(Alias)
27
+ class AliasAdmin(admin.ModelAdmin):
28
+ """Admin for Alias model."""
29
+
30
+ list_display = ("domain", "site", "is_canonical", "redirect_to_canonical")
31
+ list_filter = ("is_canonical", "redirect_to_canonical")
32
+ ordering = ("domain",)
33
+ raw_id_fields = ("site",)
34
+ readonly_fields = ("is_canonical",)
35
+ search_fields = ("domain",)
36
+
37
+
38
+ class AliasInline(admin.TabularInline):
39
+ """Inline for Alias model, showing non-canonical aliases."""
40
+
41
+ model = Alias
42
+ extra = 1
43
+ ordering = ("domain",)
44
+
45
+ def get_queryset(self, request: WSGIRequest) -> QuerySet[Alias]:
46
+ """Returns only non-canonical aliases."""
47
+ qs = self.model.aliases.get_queryset()
48
+ ordering = self.ordering or ()
49
+ if ordering:
50
+ qs = qs.order_by(*ordering)
51
+ return qs
52
+
53
+
54
+ # HACK: Monkeypatch AliasInline into SiteAdmin
55
+ SiteAdmin.inlines = type(SiteAdmin.inlines)([AliasInline]) + SiteAdmin.inlines
56
+
57
+ # HACK: Monkeypatch Alias validation into SiteForm
58
+ SiteAdmin.form = SiteForm