-
Notifications
You must be signed in to change notification settings - Fork 325
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #108 from mateuspadua/master
Specializing static and media based on tenants
- Loading branch information
Showing
11 changed files
with
410 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import os | ||
from django.utils._os import safe_join | ||
from django.db import connection | ||
from django.core.files.storage import FileSystemStorage | ||
from django.conf import settings | ||
from django.core.exceptions import ImproperlyConfigured | ||
|
||
from django.utils.encoding import filepath_to_uri | ||
from django.utils.six.moves.urllib.parse import urljoin | ||
|
||
|
||
__all__ = ( | ||
'TenantStorageMixin', | ||
'TenantFileSystemStorage', | ||
) | ||
|
||
|
||
class TenantStorageMixin(object): | ||
|
||
def path(self, name): | ||
""" | ||
To static_files is the destination path to collectstatic | ||
To media_files is the destination path to upload files | ||
""" | ||
if name is None: | ||
name = '' | ||
try: | ||
if '%s' in self.location: | ||
location = safe_join(self.location % connection.schema_name) | ||
else: | ||
location = safe_join(self.location, connection.schema_name) | ||
except AttributeError: | ||
location = self.location | ||
|
||
path = safe_join(location, name) | ||
return path | ||
|
||
|
||
class TenantFileSystemStorage(TenantStorageMixin, FileSystemStorage): | ||
""" | ||
Implementation that extends core Django's FileSystemStorage. | ||
""" | ||
|
||
def __init__(self, location=None, base_url=None, *args, **kwargs): | ||
super(TenantFileSystemStorage, self).__init__(location, base_url, *args, **kwargs) | ||
if hasattr(settings, "MULTITENANT_RELATIVE_MEDIA_ROOT") and \ | ||
settings.MULTITENANT_RELATIVE_MEDIA_ROOT: | ||
self.location = os.path.join(self.location, | ||
settings.MULTITENANT_RELATIVE_MEDIA_ROOT) | ||
|
||
relative_base_url = settings.MULTITENANT_RELATIVE_MEDIA_ROOT | ||
if not relative_base_url.endswith('/'): | ||
relative_base_url += '/' | ||
self.base_url += relative_base_url | ||
|
||
""" | ||
def path(self, name): | ||
if not hasattr(settings, "MULTITENANT_RELATIVE_MEDIA_ROOT") or \ | ||
not settings.MULTITENANT_RELATIVE_MEDIA_ROOT: | ||
raise ImproperlyConfigured("You're using the TenantFileSystemStorage " | ||
"without having set the MULTITENANT_RELATIVE_MEDIA_ROOT " | ||
"setting to a relative filesystem path as from MEDIA_ROOT.") | ||
return super(TenantFileSystemStorage, self).path(name) | ||
""" | ||
|
||
def url(self, name): | ||
if self.base_url is None: | ||
raise ValueError("This file is not accessible via a URL.") | ||
|
||
try: | ||
if '%s' in self.base_url: | ||
base_url = self.base_url % connection.schema_name | ||
else: | ||
base_url = u"{0}{1}/".format(self.base_url, connection.schema_name) | ||
except AttributeError: | ||
base_url = self.base_url | ||
|
||
return urljoin(base_url, filepath_to_uri(name)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# -*- coding: utf-8 -*- | ||
from . import TenantWrappedCommand | ||
from django.contrib.staticfiles.management.commands import collectstatic | ||
|
||
|
||
class Command(TenantWrappedCommand): | ||
COMMAND = collectstatic.Command |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import os | ||
from . import TenantWrappedCommand | ||
from compressor.management.commands import compress | ||
from django.conf import settings | ||
|
||
|
||
class Command(TenantWrappedCommand): | ||
COMMAND = compress.Command | ||
|
||
def get_tenant_from_options_or_interactive(self, **options): | ||
r = super(Command, self).get_tenant_from_options_or_interactive(**options) | ||
settings.COMPRESS_OUTPUT_DIR = os.path.join(options['schema_name'], "CACHE") | ||
return r |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
# -*- coding: utf-8 -*- | ||
import os | ||
from django.contrib.staticfiles.finders import FileSystemFinder | ||
from django.conf import settings | ||
from django.core.files.storage import FileSystemStorage | ||
from django.db import connection | ||
from collections import OrderedDict | ||
from django.core.exceptions import ImproperlyConfigured | ||
from django_tenants.utils import get_tenant_model | ||
|
||
|
||
class TenantFileSystemFinder(FileSystemFinder): | ||
def __init__(self, app_names=None, *args, **kwargs): | ||
|
||
self.locations = [] | ||
self.storages = OrderedDict() | ||
|
||
TenantModel = get_tenant_model() | ||
all_tenants = TenantModel.objects.values_list('schema_name', flat=True) | ||
# print "=========== all_tenants ============" | ||
# print all_tenants | ||
|
||
try: | ||
CURRENT_SCHEMA_TO_SERVER_STATICFILES = \ | ||
settings.CURRENT_SCHEMA_TO_SERVER_STATICFILES | ||
except AttributeError: | ||
raise ImproperlyConfigured('To use %s.%s you must ' | ||
'define the CURRENT_SCHEMA_TO_SERVER_STATICFILES ' | ||
'in your settings' % | ||
(__name__, TenantFileSystemFinder.__name__)) | ||
|
||
if not CURRENT_SCHEMA_TO_SERVER_STATICFILES: | ||
raise ImproperlyConfigured( | ||
"Your CURRENT_SCHEMA_TO_SERVER_STATICFILES setting can't be empty; " | ||
"it must have the value of the schema_name in which you are " | ||
"currently working on") | ||
else: | ||
if CURRENT_SCHEMA_TO_SERVER_STATICFILES not in all_tenants: | ||
raise ImproperlyConfigured( | ||
"The value of CURRENT_SCHEMA_TO_SERVER_STATICFILES setting " | ||
"doesnt correspond to a valid schema_name tentant") | ||
|
||
schema_name = connection.schema_name if connection.schema_name != "public" \ | ||
else CURRENT_SCHEMA_TO_SERVER_STATICFILES | ||
|
||
""" | ||
if not hasattr(settings, "MULTITENANT_RELATIVE_STATIC_ROOT") or \ | ||
not settings.MULTITENANT_RELATIVE_STATIC_ROOT: | ||
raise ImproperlyConfigured("You're using the TenantStaticFilesStorage " | ||
"without having set the MULTITENANT_RELATIVE_STATIC_ROOT " | ||
"setting to a filesystem path.") | ||
""" | ||
|
||
multitenant_relative_static_root = "" | ||
if hasattr(settings, "MULTITENANT_RELATIVE_STATIC_ROOT"): | ||
if '%s' in settings.MULTITENANT_RELATIVE_STATIC_ROOT: | ||
multitenant_relative_static_root = \ | ||
settings.MULTITENANT_RELATIVE_STATIC_ROOT % \ | ||
schema_name | ||
else: | ||
multitenant_relative_static_root = \ | ||
os.path.join(settings.MULTITENANT_RELATIVE_STATIC_ROOT, | ||
schema_name) | ||
else: | ||
multitenant_relative_static_root = schema_name | ||
|
||
multitenant_static_root = os.path.join(settings.STATIC_ROOT, | ||
multitenant_relative_static_root) | ||
|
||
# print "multitenant_relative_static_root" | ||
# print multitenant_relative_static_root | ||
# print "multitenant_static_root" | ||
# print multitenant_static_root | ||
|
||
try: | ||
multitenant_staticfiles_dirs = settings.MULTITENANT_STATICFILES_DIRS | ||
except AttributeError: | ||
raise ImproperlyConfigured('To use %s.%s you must ' | ||
'define the MULTITENANT_STATICFILES_DIRS ' | ||
'in your settings' % | ||
(__name__, TenantFileSystemFinder.__name__)) | ||
|
||
if not isinstance(multitenant_staticfiles_dirs, (list, tuple)): | ||
raise ImproperlyConfigured( | ||
"Your MULTITENANT_STATICFILES_DIRS setting is not a tuple or list; " | ||
"perhaps you forgot a trailing comma?") | ||
|
||
tenant_paths = [] | ||
for template_dir in multitenant_staticfiles_dirs: | ||
if '%s' in template_dir: | ||
tenant_paths.append(template_dir % schema_name) | ||
else: | ||
tenant_paths.append(os.path.join(template_dir, schema_name)) | ||
|
||
dirs = tenant_paths | ||
|
||
for root in dirs: | ||
if isinstance(root, (list, tuple)): | ||
prefix, root = root | ||
else: | ||
prefix = '' | ||
|
||
# print "==========================================" | ||
# print os.path.abspath(multitenant_static_root) | ||
# print os.path.abspath(root) | ||
|
||
if os.path.abspath(multitenant_static_root) == os.path.abspath(root): | ||
raise ImproperlyConfigured( | ||
"The MULTITENANT_STATICFILES_DIRS setting should " | ||
"not contain the (STATIC_ROOT + MULTITENANT_RELATIVE_STATIC_ROOT) path") | ||
if (prefix, root) not in self.locations: | ||
self.locations.append((prefix, root)) | ||
|
||
for prefix, root in self.locations: | ||
filesystem_storage = FileSystemStorage(location=root) | ||
filesystem_storage.prefix = prefix | ||
self.storages[root] = filesystem_storage |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import os | ||
from django.contrib.staticfiles.storage import StaticFilesStorage | ||
from django_tenants.files.storages import TenantStorageMixin | ||
from django.conf import settings | ||
from django.core.exceptions import ImproperlyConfigured | ||
|
||
|
||
class TenantStaticFilesStorage(TenantStorageMixin, StaticFilesStorage): | ||
""" | ||
Implementation that extends core Django's StaticFilesStorage. | ||
""" | ||
|
||
def __init__(self, location=None, base_url=None, *args, **kwargs): | ||
super(TenantStaticFilesStorage, self).__init__(location, base_url, *args, **kwargs) | ||
if hasattr(settings, "MULTITENANT_RELATIVE_STATIC_ROOT"): | ||
self.location = os.path.join(self.location, settings.MULTITENANT_RELATIVE_STATIC_ROOT) | ||
|
||
def path(self, name): | ||
""" | ||
if not hasattr(settings, "MULTITENANT_RELATIVE_STATIC_ROOT") or \ | ||
not settings.MULTITENANT_RELATIVE_STATIC_ROOT: | ||
raise ImproperlyConfigured("You're using the TenantStaticFilesStorage " | ||
"without having set the MULTITENANT_RELATIVE_STATIC_ROOT " | ||
"setting to a filesystem path.") | ||
""" | ||
return super(TenantStaticFilesStorage, self).path(name) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,6 +56,7 @@ Contents | |
use | ||
examples | ||
templates | ||
static | ||
test | ||
involved | ||
credits |
Oops, something went wrong.