Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@

intersphinx_mapping = {
'django': (
'https://docs.djangoproject.com/en/1.11/',
'https://docs.djangoproject.com/en/1.11/_objects/'),
'https://docs.djangoproject.com/en/4.2/',
'https://docs.djangoproject.com/en/4.2/_objects/'),
}

# -- Options for HTML output ---------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion docs/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ Or you can create a completely separate project for the main website.
Caching
-------

To enable tenant aware caching you can set the `KEY_FUNCTION <https://docs.djangoproject.com/en/1.8/ref/settings/#std:setting-CACHES-KEY_FUNCTION>`_ setting to use the provided ``make_key`` helper function which
To enable tenant aware caching you can set the `KEY_FUNCTION <https://docs.djangoproject.com/en/4.2/ref/settings/#key-function>`_ setting to use the provided ``make_key`` helper function which
adds the tenants ``schema_name`` as the first key prefix.

.. code-block:: python
Expand Down
4 changes: 2 additions & 2 deletions examples/tenant_tutorial/customers/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class TenantView(FormView):
success_url = "/"

def get_context_data(self, **kwargs):
context = super(TenantView, self).get_context_data(**kwargs)
context = super().get_context_data(**kwargs)
context['tenants_list'] = Client.objects.all()
context['users'] = User.objects.all()
return context
Expand Down Expand Up @@ -41,4 +41,4 @@ def form_valid(self, form):
except DatabaseError:
pass

return super(TenantView, self).form_valid(form)
return super().form_valid(form)
2 changes: 1 addition & 1 deletion examples/tenant_tutorial/tenant_tutorial/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class HomeView(TemplateView):
template_name = "index_public.html"

def get_context_data(self, **kwargs):
context = super(HomeView, self).get_context_data(**kwargs)
context = super().get_context_data(**kwargs)

hostname_without_port = remove_www(self.request.get_host().split(':')[0])

Expand Down
8 changes: 4 additions & 4 deletions src/tenant_schemas/management/commands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def __new__(cls, *args, **kwargs):
"""
Sets option_list and help dynamically.
"""
obj = super(BaseTenantCommand, cls).__new__(cls, *args, **kwargs)
obj = super().__new__(cls, *args, **kwargs)

app_name = get_commands()[obj.COMMAND_NAME]
if isinstance(app_name, BaseCommand):
Expand All @@ -43,7 +43,7 @@ def __new__(cls, *args, **kwargs):
return obj

def add_arguments(self, parser):
super(BaseTenantCommand, self).add_arguments(parser)
super().add_arguments(parser)
parser.add_argument("-s", "--schema", dest="schema_name")
parser.add_argument(
"-p",
Expand Down Expand Up @@ -148,12 +148,12 @@ class variable COMMAND_NAME of the subclass.
"""

def __new__(cls, *args, **kwargs):
obj = super(TenantWrappedCommand, cls).__new__(cls, *args, **kwargs)
obj = super().__new__(cls, *args, **kwargs)
obj.command_instance = obj.COMMAND()
return obj

def add_arguments(self, parser):
super(TenantWrappedCommand, self).add_arguments(parser)
super().add_arguments(parser)
self.command_instance.add_arguments(parser)

def handle(self, *args, **options):
Expand Down
2 changes: 1 addition & 1 deletion src/tenant_schemas/management/commands/migrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def handle(self, *args, **options):
raise CommandError("migrate has been disabled, for database '{0}'. Use migrate_schemas "
"instead. Please read the documentation if you don't know why you "
"shouldn't call migrate directly!".format(database))
super(Command, self).handle(*args, **options)
super().handle(*args, **options)


if django_is_in_test_mode():
Expand Down
4 changes: 2 additions & 2 deletions src/tenant_schemas/management/commands/migrate_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ class Command(SyncCommon):
)

def add_arguments(self, parser):
super(Command, self).add_arguments(parser)
super().add_arguments(parser)
command = MigrateCommand()
command.add_arguments(parser)

def handle(self, *args, **options):
super(Command, self).handle(*args, **options)
super().handle(*args, **options)
self.PUBLIC_SCHEMA_NAME = get_public_schema_name()

executor = get_executor(codename=self.executor)(self.args, self.options)
Expand Down
4 changes: 2 additions & 2 deletions src/tenant_schemas/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def save(self, verbosity=1, *args, **kwargs):
"the public schema. Current schema is %s."
% connection.schema_name)

super(TenantMixin, self).save(*args, **kwargs)
super().save(*args, **kwargs)

if is_new and self.auto_create_schema:
try:
Expand All @@ -91,7 +91,7 @@ def delete(self, force_drop=False, *args, **kwargs):
cursor = connection.cursor()
cursor.execute('DROP SCHEMA IF EXISTS %s CASCADE' % self.schema_name)

return super(TenantMixin, self).delete(*args, **kwargs)
return super().delete(*args, **kwargs)

def create_schema(self, check_if_exists=False, sync_schema=True,
verbosity=1):
Expand Down
12 changes: 6 additions & 6 deletions src/tenant_schemas/postgresql_backend/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class DatabaseWrapper(original_backend.DatabaseWrapper):
include_public_schema = True

def __init__(self, *args, **kwargs):
super(DatabaseWrapper, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)

# Use a patched version of the DatabaseIntrospection that only returns the table list for the
# currently selected schema.
Expand All @@ -62,10 +62,10 @@ def __init__(self, *args, **kwargs):

def close(self):
self.search_path_set = False
super(DatabaseWrapper, self).close()
super().close()

def rollback(self):
super(DatabaseWrapper, self).rollback()
super().rollback()
# Django's rollback clears the search path so we have to set it again the next time.
self.search_path_set = False

Expand Down Expand Up @@ -121,10 +121,10 @@ def _cursor(self, name=None):
must go through this to get the cursor handle. We change the path.
"""
if name:
# Only supported and required by Django 1.11 (server-side cursor)
cursor = super(DatabaseWrapper, self)._cursor(name=name)
# Create server-side cursor (supported across Django versions)
cursor = super()._cursor(name=name)
else:
cursor = super(DatabaseWrapper, self)._cursor()
cursor = super()._cursor()

# optionally limit the number of executions - under load, the execution
# of `set search_path` can be quite time consuming
Expand Down
12 changes: 3 additions & 9 deletions src/tenant_schemas/postgresql_backend/introspection.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
from __future__ import unicode_literals

from collections import namedtuple

from django.db.backends.base.introspection import (
BaseDatabaseIntrospection, FieldInfo, TableInfo,
)
try:
# Django >= 1.11
from django.db.models.indexes import Index
except ImportError:
Index = None
from django.db.models.indexes import Index
from django.utils.encoding import force_str

fields = FieldInfo._fields
Expand Down Expand Up @@ -175,7 +169,7 @@ class DatabaseSchemaIntrospection(BaseDatabaseIntrospection):
"""

def get_field_type(self, data_type, description):
field_type = super(DatabaseSchemaIntrospection, self).get_field_type(data_type, description)
field_type = super().get_field_type(data_type, description)
if description.default and 'nextval' in description.default:
if field_type == 'IntegerField':
return 'AutoField'
Expand Down Expand Up @@ -310,7 +304,7 @@ def get_constraints(self, cursor, table_name):
"foreign_key": None,
"check": False,
"index": True,
"type": Index.suffix if type_ == 'btree' and Index else type_,
"type": Index.suffix if type_ == 'btree' else type_,
"definition": definition,
"options": options,
}
Expand Down
16 changes: 4 additions & 12 deletions src/tenant_schemas/routers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
from django.conf import settings
from django.db.models.base import ModelBase
from django.db import connection
from django.db.utils import load_backend

from tenant_schemas.postgresql_backend.base import DatabaseWrapper as TenantDbWrapper
from tenant_schemas.utils import app_labels, get_public_schema_name


class TenantSyncRouter(object):
"""
Expand All @@ -10,20 +13,12 @@ class TenantSyncRouter(object):
"""

def allow_migrate(self, db, app_label, model_name=None, **hints):
# the imports below need to be done here else django <1.5 goes crazy
# https://code.djangoproject.com/ticket/20704
from django.db import connection
from tenant_schemas.utils import get_public_schema_name, app_labels
from tenant_schemas.postgresql_backend.base import DatabaseWrapper as TenantDbWrapper

db_engine = settings.DATABASES[db]['ENGINE']
if not (db_engine == 'tenant_schemas.postgresql_backend' or
issubclass(getattr(load_backend(db_engine), 'DatabaseWrapper'), TenantDbWrapper)):
return None

if isinstance(app_label, ModelBase):
# In django <1.7 the `app_label` parameter is actually `model`
app_label = app_label._meta.app_label

if connection.schema_name == get_public_schema_name():
if app_label not in app_labels(settings.SHARED_APPS):
Expand All @@ -34,6 +29,3 @@ def allow_migrate(self, db, app_label, model_name=None, **hints):

return None

def allow_syncdb(self, db, model):
# allow_syncdb was changed to allow_migrate in django 1.7
return self.allow_migrate(db, model)
4 changes: 2 additions & 2 deletions src/tenant_schemas/template_loaders.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

class CachedLoader(cached.Loader):
def cache_key(self, *args, **kwargs):
key = super(CachedLoader, self).cache_key(*args, **kwargs)
key = super().cache_key(*args, **kwargs)

if not connection.tenant or isinstance(connection.tenant, FakeTenant):
return key
Expand All @@ -23,7 +23,7 @@ def cache_key(self, *args, **kwargs):

class FilesystemLoader(filesystem.Loader):
def get_dirs(self):
dirs = OrderedSet(super(FilesystemLoader, self).get_dirs())
dirs = OrderedSet(super().get_dirs())

if connection.tenant and not isinstance(connection.tenant, FakeTenant):
try:
Expand Down
4 changes: 2 additions & 2 deletions src/tenant_schemas/templatetags/tenant.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

class SchemaURLNode(URLNode):
def __init__(self, url_node):
super(SchemaURLNode, self).__init__(url_node.view_name, url_node.args, url_node.kwargs, url_node.asvar)
super().__init__(url_node.view_name, url_node.args, url_node.kwargs, url_node.asvar)

def render(self, context):
url = super(SchemaURLNode, self).render(context)
url = super().render(context)
return clean_tenant_url(url)


Expand Down
24 changes: 12 additions & 12 deletions src/tenant_schemas/test/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,75 +6,75 @@ class TenantRequestFactory(RequestFactory):
tm = TenantMiddleware(lambda r:r)

def __init__(self, tenant, **defaults):
super(TenantRequestFactory, self).__init__(**defaults)
super().__init__(**defaults)
self.tenant = tenant

def get(self, path, data={}, **extra):
if 'HTTP_HOST' not in extra:
extra['HTTP_HOST'] = self.tenant.domain_url

return super(TenantRequestFactory, self).get(path, data, **extra)
return super().get(path, data, **extra)

def post(self, path, data={}, **extra):
if 'HTTP_HOST' not in extra:
extra['HTTP_HOST'] = self.tenant.domain_url

return super(TenantRequestFactory, self).post(path, data, **extra)
return super().post(path, data, **extra)

def patch(self, path, data={}, **extra):
if 'HTTP_HOST' not in extra:
extra['HTTP_HOST'] = self.tenant.domain_url

return super(TenantRequestFactory, self).patch(path, data, **extra)
return super().patch(path, data, **extra)

def put(self, path, data={}, **extra):
if 'HTTP_HOST' not in extra:
extra['HTTP_HOST'] = self.tenant.domain_url

return super(TenantRequestFactory, self).put(path, data, **extra)
return super().put(path, data, **extra)

def delete(self, path, data='', content_type='application/octet-stream',
**extra):
if 'HTTP_HOST' not in extra:
extra['HTTP_HOST'] = self.tenant.domain_url

return super(TenantRequestFactory, self).delete(path, data, **extra)
return super().delete(path, data, **extra)


class TenantClient(Client):
tm = TenantMiddleware(lambda r:r)

def __init__(self, tenant, enforce_csrf_checks=False, **defaults):
super(TenantClient, self).__init__(enforce_csrf_checks, **defaults)
super().__init__(enforce_csrf_checks, **defaults)
self.tenant = tenant

def get(self, path, data={}, **extra):
if 'HTTP_HOST' not in extra:
extra['HTTP_HOST'] = self.tenant.domain_url

return super(TenantClient, self).get(path, data, **extra)
return super().get(path, data, **extra)

def post(self, path, data={}, **extra):
if 'HTTP_HOST' not in extra:
extra['HTTP_HOST'] = self.tenant.domain_url

return super(TenantClient, self).post(path, data, **extra)
return super().post(path, data, **extra)

def patch(self, path, data={}, **extra):
if 'HTTP_HOST' not in extra:
extra['HTTP_HOST'] = self.tenant.domain_url

return super(TenantClient, self).patch(path, data, **extra)
return super().patch(path, data, **extra)

def put(self, path, data={}, **extra):
if 'HTTP_HOST' not in extra:
extra['HTTP_HOST'] = self.tenant.domain_url

return super(TenantClient, self).put(path, data, **extra)
return super().put(path, data, **extra)

def delete(self, path, data='', content_type='application/octet-stream',
**extra):
if 'HTTP_HOST' not in extra:
extra['HTTP_HOST'] = self.tenant.domain_url

return super(TenantClient, self).delete(path, data, **extra)
return super().delete(path, data, **extra)
4 changes: 2 additions & 2 deletions src/tenant_schemas/tests/test_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class MissingDefaultTenantMiddleware(DefaultTenantMiddleware):
class RoutesTestCase(BaseTestCase):
@classmethod
def setUpClass(cls):
super(RoutesTestCase, cls).setUpClass()
super().setUpClass()
settings.SHARED_APPS = ("tenant_schemas",)
settings.TENANT_APPS = (
"dts_test_app",
Expand All @@ -36,7 +36,7 @@ def setUpClass(cls):
cls.public_tenant.save(verbosity=BaseTestCase.get_verbosity())

def setUp(self):
super(RoutesTestCase, self).setUp()
super().setUp()
self.factory = RequestFactory()
self.tm = TenantMiddleware(lambda r: r)
self.dtm = DefaultTenantMiddleware(lambda r: r)
Expand Down
11 changes: 3 additions & 8 deletions src/tenant_schemas/tests/test_tenants.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,7 @@
tenant_context,
)

try:
# python 2
from StringIO import StringIO
except ImportError:
# python 3
from io import StringIO
from io import StringIO


class TenantDataAndSettingsTest(BaseTestCase):
Expand All @@ -30,7 +25,7 @@ class TenantDataAndSettingsTest(BaseTestCase):

@classmethod
def setUpClass(cls):
super(TenantDataAndSettingsTest, cls).setUpClass()
super().setUpClass()
settings.SHARED_APPS = ("tenant_schemas",)
settings.TENANT_APPS = (
"dts_test_app",
Expand Down Expand Up @@ -308,7 +303,7 @@ def test_command(self):
class SharedAuthTest(BaseTestCase):
@classmethod
def setUpClass(cls):
super(SharedAuthTest, cls).setUpClass()
super().setUpClass()
settings.SHARED_APPS = (
"tenant_schemas",
"django.contrib.auth",
Expand Down
Loading