PEP8 and typos

This commit is contained in:
Anton Ovchinnikov 2014-08-21 10:25:04 +02:00 committed by Anton Ovchinnikov
parent 419bbd4aa1
commit f740df449d
16 changed files with 50 additions and 41 deletions

View File

@ -17,7 +17,7 @@ A schema can be seen as a directory in an operating system, each directory (sche
Why schemas
-----------
There are typically three solutions for solving the multinancy problem.
There are typically three solutions for solving the multitenancy problem.
1. Isolated Approach: Separate Databases. Each tenant has it's own database.
@ -30,7 +30,7 @@ This application implements the second approach, which in our opinion, represent
* Simplicity: barely make any changes to your current code to support multitenancy. Plus, you only manage one database.
* Performance: make use of shared connections, buffers and memory.
Each solution has it's up and down sides, for a more in-depth discussion, see Microsoft's excelent article on [Multi-Tenant Data Architecture](http://msdn.microsoft.com/en-us/library/aa479086.aspx).
Each solution has it's up and down sides, for a more in-depth discussion, see Microsoft's excellent article on [Multi-Tenant Data Architecture](http://msdn.microsoft.com/en-us/library/aa479086.aspx).
How it works
------------

View File

@ -14,7 +14,7 @@ A schema can be seen as a directory in an operating system, each directory (sche
Why schemas?
------------
There are typically three solutions for solving the multinancy problem.
There are typically three solutions for solving the multitenancy problem.
1. Isolated Approach: Separate Databases. Each tenant has it's own database.
@ -27,7 +27,7 @@ This application implements the second approach, which in our opinion, represent
* Simplicity: barely make any changes to your current code to support multitenancy. Plus, you only manage one database.
* Performance: make use of shared connections, buffers and memory.
Each solution has it's up and down sides, for a more in-depth discussion, see Microsoft's excelent article on `Multi-Tenant Data Architecture <http://msdn.microsoft.com/en-us/library/aa479086.aspx>`_.
Each solution has it's up and down sides, for a more in-depth discussion, see Microsoft's excellent article on `Multi-Tenant Data Architecture <http://msdn.microsoft.com/en-us/library/aa479086.aspx>`_.
How it works
------------

View File

@ -9,7 +9,7 @@ Assuming you have django installed, the first step is to install ``django-tenant
Basic Settings
==============
You'll have to make the following modifcations to your ``settings.py`` file.
You'll have to make the following modifications to your ``settings.py`` file.
Your ``DATABASE_ENGINE`` setting needs to be changed to
@ -153,7 +153,7 @@ We override ``south``'s ``syncdb`` and ``migrate`` command, so you'll need to ch
INSTALLED_APPS = SHARED_APPS + TENANT_APPS + ('tenant_schemas',)
This makes sure ``tenant_schemas`` is the last on the list and therefore always has precedence when running an overriden command.
This makes sure ``tenant_schemas`` is the last on the list and therefore always has precedence when running an overridden command.
Optional Settings
=================

View File

@ -59,13 +59,13 @@ You can also use the option ``--tenant`` to only sync tenant apps or ``--shared`
.. code-block:: bash
./manage.py sync_schemas --shared # will only sync the public schema
./manage.py sync_schemas --shared # will only sync the public schema
We've also packed south's migrate command in a compatible way with this app. It will also respect the ``SHARED_APPS`` and ``TENANT_APPS`` settings, so if you're migrating the ``public`` schema it will only migrate ``SHARED_APPS``. If you're migrating tenants, it will only migrate ``TENANT_APPS``.
.. code-block:: bash
./manage.py migrate_schemas
./manage.py migrate_schemas
The options given to ``migrate_schemas`` are also passed to every ``migrate``. Hence you may find handy

View File

@ -11,12 +11,12 @@ MANAGERS = ADMINS
DATABASES = {
'default': {
'ENGINE': 'tenant_schemas.postgresql_backend', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
'ENGINE': 'tenant_schemas.postgresql_backend', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
'NAME': 'tenant_tutorial', # Or path to database file if using sqlite3.
'USER': 'postgres',
'PASSWORD': 'root',
'HOST': 'localhost', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
'PORT': '', # Set to empty string for default.
'HOST': 'localhost', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
'PORT': '', # Set to empty string for default.
}
}
@ -118,7 +118,7 @@ PUBLIC_SCHEMA_URLCONF = 'tenant_tutorial.urls_public'
WSGI_APPLICATION = 'tenant_tutorial.wsgi.application'
import os
TEMPLATE_DIRS = (os.path.join(os.path.dirname(__file__), '..', 'templates').replace('\\','/'),)
TEMPLATE_DIRS = (os.path.join(os.path.dirname(__file__), '..', 'templates').replace('\\', '/'),)
SHARED_APPS = (
'tenant_schemas', # mandatory

View File

@ -2,6 +2,7 @@
from os.path import exists
from version import get_git_version
try:
from setuptools import setup
except ImportError:
@ -15,24 +16,24 @@ setup(
author='Bernardo Pires Carneiro',
author_email='carneiro.be@gmail.com',
packages=[
'tenant_schemas',
'tenant_schemas.postgresql_backend',
'tenant_schemas.management',
'tenant_schemas.management.commands',
'tenant_schemas.templatetags',
'tenant_schemas.test',
'tenant_schemas.tests',
'tenant_schemas',
'tenant_schemas.postgresql_backend',
'tenant_schemas.management',
'tenant_schemas.management.commands',
'tenant_schemas.templatetags',
'tenant_schemas.test',
'tenant_schemas.tests',
],
scripts=[],
url='https://github.com/bcarneiro/django-tenant-schemas',
license='MIT',
description='Tenant support for Django using PostgreSQL schemas.',
long_description=open('README.markdown').read() if exists("README.markdown") else "",
classifiers=[
'License :: OSI Approved :: MIT License',
'Framework :: Django',
'Programming Language :: Python',
],
classifiers=[
'License :: OSI Approved :: MIT License',
'Framework :: Django',
'Programming Language :: Python',
],
install_requires=[
'Django >= 1.2.0',
'psycopg2',

View File

@ -6,7 +6,7 @@ from tenant_schemas.utils import get_public_schema_name, get_tenant_model
recommended_config = """
Warning: You should put 'tenant_schemas' at the end of INSTALLED_APPS like this:
INSTALLED_APPS = TENANT_APPS + SHARED_APPS + ('tenant_schemas',)
This is neccesary to overwrite built-in django management commands with their schema-aware implementations.
This is necessary to overwrite built-in django management commands with their schema-aware implementations.
"""
# Make a bunch of tests for configuration recommendations
# These are best practices basically, to avoid hard to find bugs, unexpected behaviour
@ -25,8 +25,8 @@ if hasattr(settings, 'PG_EXTRA_SEARCH_PATHS'):
# make sure no tenant schema is in settings.PG_EXTRA_SEARCH_PATHS
invalid_schemas = set(settings.PG_EXTRA_SEARCH_PATHS).intersection(
get_tenant_model().objects.all().values_list('schema_name', flat=True))
get_tenant_model().objects.all().values_list('schema_name', flat=True))
if invalid_schemas:
raise ImproperlyConfigured("Do not include tenant schemas (%s) on PG_EXTRA_SEARCH_PATHS."
raise ImproperlyConfigured("Do not include tenant schemas (%s) on PG_EXTRA_SEARCH_PATHS."
% list(invalid_schemas))

View File

@ -3,6 +3,7 @@ from django.conf import settings
from django.core.management import call_command, get_commands, load_command_class
from django.core.management.base import BaseCommand, NoArgsCommand, CommandError
from django.db import connection
try:
from django.utils.six.moves import input
except ImportError:
@ -16,6 +17,7 @@ class BaseTenantCommand(BaseCommand):
over all schemata. The actual command name is expected in the
class variable COMMAND_NAME of the subclass.
"""
def __new__(cls, *args, **kwargs):
"""
Sets option_list and help dynamically.
@ -39,7 +41,7 @@ class BaseTenantCommand(BaseCommand):
)
# prepend the command's original help with the info about schemata iteration
obj.help = "Calls %s for all registered schemata. You can use regular %s options. "\
obj.help = "Calls %s for all registered schemata. You can use regular %s options. " \
"Original help for %s: %s" % (obj.COMMAND_NAME, obj.COMMAND_NAME, obj.COMMAND_NAME,
getattr(cmdclass, 'help', 'none'))
return obj
@ -49,9 +51,9 @@ class BaseTenantCommand(BaseCommand):
if verbosity >= 1:
print()
print(self.style.NOTICE("=== Switching to schema '") \
+ self.style.SQL_TABLE(tenant.schema_name)\
+ self.style.NOTICE("' then calling %s:" % command_name))
print(self.style.NOTICE("=== Switching to schema '")
+ self.style.SQL_TABLE(tenant.schema_name)
+ self.style.NOTICE("' then calling %s:" % command_name))
connection.set_tenant(tenant)
@ -65,10 +67,11 @@ class BaseTenantCommand(BaseCommand):
if options['schema_name']:
# only run on a particular schema
connection.set_schema_to_public()
self.execute_command(get_tenant_model().objects.get(schema_name=options['schema_name']), self.COMMAND_NAME, *args, **options)
self.execute_command(get_tenant_model().objects.get(schema_name=options['schema_name']), self.COMMAND_NAME,
*args, **options)
else:
for tenant in get_tenant_model().objects.all():
if not(options['skip_public'] and tenant.schema_name == get_public_schema_name()):
if not (options['skip_public'] and tenant.schema_name == get_public_schema_name()):
self.execute_command(tenant, self.COMMAND_NAME, *args, **options)
@ -110,6 +113,7 @@ class TenantWrappedCommand(InteractiveTenantOption, BaseCommand):
on a particular tenant. The actual command name is expected in the
class variable COMMAND_NAME of the subclass.
"""
def __new__(cls, *args, **kwargs):
obj = super(TenantWrappedCommand, cls).__new__(cls, *args, **kwargs)
obj.command_instance = obj.COMMAND()

View File

@ -11,7 +11,7 @@ class Command(InteractiveTenantOption, BaseCommand):
def run_from_argv(self, argv):
"""
Changes the option_list to use the options from the wrapped command.
Adds schema parameter to specifiy which schema will be used when
Adds schema parameter to specify which schema will be used when
executing the wrapped command.
"""
# load the command object.

View File

@ -19,7 +19,7 @@ class TenantMiddleware(object):
def process_request(self, request):
# connection needs first to be at the public schema, as this is where the
# tenant informations are saved
# tenant metadata is stored
connection.set_schema_to_public()
hostname = self.hostname_from_request(request)

View File

@ -14,7 +14,7 @@ class TenantMixin(models.Model):
# removed after tenant remove.
auto_create_schema = True # set this flag to false on a parent class if
# you dont want the schema to be automatically
# you don't want the schema to be automatically
# created upon save.
domain_url = models.CharField(max_length=128, unique=True)

View File

@ -41,7 +41,6 @@ class DatabaseWrapper(original_backend.DatabaseWrapper):
self.set_settings_schema(self.schema_name)
self.search_path_set = False
def set_schema(self, schema_name, include_public=True):
"""
Main API method to current database schema,

View File

@ -12,6 +12,7 @@ from django.utils.encoding import force_bytes
from django.utils._os import safe_join
from django.db import connection
class CachedLoader(BaseLoader):
is_usable = True
@ -49,7 +50,8 @@ class CachedLoader(BaseLoader):
if template_dirs:
# If template directories were specified, use a hash to differentiate
if connection.tenant:
key = '-'.join([str(connection.tenant.pk), template_name, hashlib.sha1(force_bytes('|'.join(template_dirs))).hexdigest()])
key = '-'.join([str(connection.tenant.pk), template_name,
hashlib.sha1(force_bytes('|'.join(template_dirs))).hexdigest()])
else:
key = '-'.join([template_name, hashlib.sha1(force_bytes('|'.join(template_dirs))).hexdigest()])
@ -71,6 +73,7 @@ class CachedLoader(BaseLoader):
"Empty the template cache."
self.template_cache.clear()
class FilesystemLoader(BaseLoader):
is_usable = True
@ -86,7 +89,8 @@ class FilesystemLoader(BaseLoader):
try:
template_dirs = settings.MULTITENANT_TEMPLATE_DIRS
except AttributeError:
raise ImproperlyConfigured('To use %s.%s you must define the MULTITENANT_TEMPLATE_DIRS' % (__name__, FilesystemLoader.__name__))
raise ImproperlyConfigured('To use %s.%s you must define the MULTITENANT_TEMPLATE_DIRS' %
(__name__, FilesystemLoader.__name__))
for template_dir in template_dirs:
try:
yield safe_join(template_dir, connection.tenant.domain_url, template_name)

View File

@ -22,7 +22,7 @@ class DummyModel(models.Model):
Just a test model so we can test manipulating data
inside a tenant
"""
name = models.CharField(max_length=1337) # every dummy should have a pretty name :)
name = models.CharField(max_length=1337) # every dummy should have a pretty name :)
def __unicode__(self):
return self.name

View File

@ -7,7 +7,7 @@ from ..utils import get_public_schema_name
class BaseTestCase(TransactionTestCase):
""" Base testcase that comes packed with overloaded INSTALLED_APPS,
""" Base test case that comes packed with overloaded INSTALLED_APPS,
custom public tenant, and schemas cleanup on tearDown.
"""
@classmethod

View File

@ -38,6 +38,7 @@ def get_tenant_model():
def get_public_schema_name():
return getattr(settings, 'PUBLIC_SCHEMA_NAME', 'public')
def get_limit_set_calls():
return getattr(settings, 'TENANT_LIMIT_SET_CALLS', False)