Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added django>=2.0 compat #551

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 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
6 changes: 4 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@ sudo: false
language: python
python:
- 2.7
- 3.4
- 3.5
- 3.6
services:
- postgresql
addons:
postgresql: '9.4'
install: pip install -q tox-travis
env:
- DJANGO=1.8
- DJANGO=1.10
- DJANGO=1.11
- DJANGO=2.0
- DJANGO=2.1
matrix:
fast_finish: true
script: tox
Expand Down
10 changes: 4 additions & 6 deletions dts_test_project/dts_test_app/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations
from django.db import migrations, models
import django.db.models.deletion
from django.conf import settings


Expand All @@ -25,11 +26,8 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='ModelWithFkToPublicUser',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
},
bases=(models.Model,),
),
]
7 changes: 6 additions & 1 deletion dts_test_project/dts_test_app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,9 @@ def __unicode__(self):


class ModelWithFkToPublicUser(models.Model):
user = models.ForeignKey(User)
"""Test model with foreign key."""

user = models.ForeignKey(
User,
on_delete=models.CASCADE
)
8 changes: 4 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,17 @@
classifiers=[
'License :: OSI Approved :: MIT License',
'Framework :: Django',
'Framework :: Django :: 1.8',
'Framework :: Django :: 1.9',
'Framework :: Django :: 1.10',
'Framework :: Django :: 1.11',
'Framework :: Django :: 2.0',
'Framework :: Django :: 2.1',
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AGASS007 great!
are you planning to release a new version soon?

'Programming Language :: Python',
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3.5",
"Topic :: Database",
"Topic :: Software Development :: Libraries",
],
install_requires=[
'Django >= 1.8.0',
'Django >= 1.11.0',
'psycopg2',
],
zip_safe=False,
Expand Down
23 changes: 14 additions & 9 deletions tenant_schemas/management/commands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,27 +86,31 @@ class InteractiveTenantOption(object):
def add_arguments(self, parser):
parser.add_argument("-s", "--schema", dest="schema_name", help="specify tenant schema")

def get_tenant_from_options_or_interactive(self, **options):
def get_tenant_from_options_or_interactive(self, schema_name=None):
TenantModel = get_tenant_model()
all_tenants = TenantModel.objects.all()
values = TenantModel.objects.values_list(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of values_list() why not use only("schema_name", "domain_url")? That way you can still keep the (t.schema_name, t.domain_url,) for t in all_tenants]) because the way youre doing it now, the order can be reversed depending on the python version.

"schema_name", "domain_url"
)

if not all_tenants:
if not values:
raise CommandError("""There are no tenants in the system.
To learn how create a tenant, see:
https://django-tenant-schemas.readthedocs.io/en/latest/use.html#creating-a-tenant""")

if options.get('schema_name'):
tenant_schema = options['schema_name']
if schema_name is not None:
tenant_schema = schema_name
else:
while True:
tenant_schema = input("Enter Tenant Schema ('?' to list schemas): ")
if tenant_schema == '?':
print('\n'.join(["%s - %s" % (t.schema_name, t.domain_url,) for t in all_tenants]))
print('\n'.join(["%s - %s" % item for item in values]))
else:
break

if tenant_schema not in [t.schema_name for t in all_tenants]:
raise CommandError("Invalid tenant schema, '%s'" % (tenant_schema,))
if tenant_schema not in [schema_name for schema_name, _ in values]:
raise CommandError(
"Invalid tenant schema, '%s'" % (tenant_schema,)
)

return TenantModel.objects.get(schema_name=tenant_schema)

Expand All @@ -130,7 +134,8 @@ def add_arguments(self, parser):
self.command_instance.add_arguments(parser)

def handle(self, *args, **options):
tenant = self.get_tenant_from_options_or_interactive(**options)
schema_name = options.pop("schema_name", None)
tenant = self.get_tenant_from_options_or_interactive(schema_name)
connection.set_tenant(tenant)

self.command_instance.execute(*args, **options)
Expand Down
21 changes: 17 additions & 4 deletions tenant_schemas/management/commands/tenant_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@
class Command(InteractiveTenantOption, BaseCommand):
help = "Wrapper around django commands for use with an individual tenant"

def add_arguments(self, parser):
super(Command, self).add_arguments(parser)

parser.add_argument("original_command_name")
parser.add_argument("original_command_args", nargs="*")
parser.add_argument("--original_command_options", nargs="*")

def run_from_argv(self, argv):
"""
Changes the option_list to use the options from the wrapped command.
Expand All @@ -26,8 +33,9 @@ def run_from_argv(self, argv):
else:
klass = load_command_class(app_name, argv[2])

# Ugly, but works. Delete tenant_command from the argv, parse the schema manually
# and forward the rest of the arguments to the actual command being wrapped.
# Ugly, but works. Delete tenant_command from the argv, parse the
# schema manually and forward the rest of the arguments to the actual
# command being wrapped.
del argv[1]
schema_parser = argparse.ArgumentParser()
schema_parser.add_argument("-s", "--schema", dest="schema_name", help="specify tenant schema")
Expand All @@ -38,6 +46,11 @@ def run_from_argv(self, argv):
klass.run_from_argv(args)

def handle(self, *args, **options):
tenant = self.get_tenant_from_options_or_interactive(**options)
schema_name = options.pop("schema_name", None)
tenant = self.get_tenant_from_options_or_interactive(schema_name)
connection.set_tenant(tenant)
call_command(*args, **options)

command_name = options.pop("original_command_name")
args += tuple(options.pop("original_command_args"))
options.update(options.pop("original_command_options", {}))
call_command(command_name, *args, **options)
5 changes: 1 addition & 4 deletions tenant_schemas/postgresql_backend/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@
from tenant_schemas.utils import get_public_schema_name, get_limit_set_calls
from tenant_schemas.postgresql_backend.introspection import DatabaseSchemaIntrospection


ORIGINAL_BACKEND = getattr(settings, 'ORIGINAL_BACKEND', 'django.db.backends.postgresql_psycopg2')
# Django 1.9+ takes care to rename the default backend to 'django.db.backends.postgresql'
original_backend = django.db.utils.load_backend(ORIGINAL_BACKEND)
original_backend = django.db.utils.load_backend('django.db.backends.postgresql')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can cause issues, i can see the need to not break this, i can come up with a couple scenarios on why you would want to override this.


EXTRA_SEARCH_PATHS = getattr(settings, 'PG_EXTRA_SEARCH_PATHS', [])

Expand Down
8 changes: 2 additions & 6 deletions tenant_schemas/postgresql_backend/introspection.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@
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_text

fields = FieldInfo._fields
Expand Down Expand Up @@ -310,7 +306,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
Loading