Search code examples
pythondjangodynamicmodelmulti-tenant

Issue with saving dynamic model object in Django (with djano-tenant-schema)


I am having issue in dynamically generating user for my Django app, where I'm using the django-tenant-schemas for multi tenancy.

Following is my views snippet:

def RegisterView(request):
if request.method == 'POST':
    response_data = {}
    domain = request.POST.get('domain')
    schema = request.POST.get('schema')
    name = request.POST.get('name')
    description = request.POST.get('description')

    client=Client()
    Client.domain_url=domain
    Client.schema_name=schema
    Client.name=name
    Client.description=description
    Client.save()

Now, I import the model Client under a separate app customers using

from customers.models import Client

For this multi tenant package, all models inherit the base TenantMixin.

Following is my model:

class Client(TenantMixin):
name = models.CharField(max_length=100)
description = models.TextField(max_length=200)
created_on = models.DateField(auto_now_add=True)

And this is the TenanMixin code snippet with the commands for your ready help:

class TenantMixin(models.Model):
"""
All tenant models must inherit this class.
"""

auto_drop_schema = False
"""
USE THIS WITH CAUTION!
Set this flag to true on a parent class if you want the schema to be
automatically deleted if the tenant row gets deleted.
"""

auto_create_schema = True
"""
Set this flag to false on a parent class if you don't want the schema
to be automatically created upon save.
"""

domain_url = models.CharField(max_length=128, unique=True)
schema_name = models.CharField(max_length=63, unique=True,
                               validators=[_check_schema_name])

class Meta:
    abstract = True

def save(self, verbosity=1, *args, **kwargs):
    is_new = self.pk is None

    if is_new and connection.schema_name != get_public_schema_name():
        raise Exception("Can't create tenant outside the public schema. "
                        "Current schema is %s." % connection.schema_name)
    elif not is_new and connection.schema_name not in (self.schema_name, get_public_schema_name()):
        raise Exception("Can't update tenant outside it's own schema or "
                        "the public schema. Current schema is %s."
                        % connection.schema_name)

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

    if is_new and self.auto_create_schema:
        try:
            self.create_schema(check_if_exists=True, verbosity=verbosity)
        except:
            # We failed creating the tenant, delete what we created and
            # re-raise the exception
            self.delete(force_drop=True)
            raise
        else:
            post_schema_sync.send(sender=TenantMixin, tenant=self)

Now, error I'm getting is:

save() missing 1 required positional argument: 'self'

And the traceback is:

Traceback:  

File "/home/sayantan/Desktop/djangowork/my_env/lib/python3.4/site- packages/django/core/handlers/base.py" in get_response
  149.                     response =     self.process_exception_by_middleware(e, request)

File "/home/sayantan/Desktop/djangowork/my_env/lib/python3.4/site-    packages/django/core/handlers/base.py" in get_response
  147.                     response = wrapped_callback(request,  *callback_args, **callback_kwargs)

File "/home/sayantan/Desktop/djangowork/invoice/invoice/views.py" in RegisterView
  55.         Client.save()

Exception Type: TypeError at /register/
Exception Value: save() missing 1 required positional argument: 'self'

Request you to kindly help me, if possible.


Solution

  • That's probably happening because you are instantiating your Client model on your client variable but instead of using the instance of the class, you are assigning the data directly to the Class. You should save() your object and not the Class itself (as you can see here and here)

    def RegisterView(request):
        if request.method == 'POST':
        response_data = {}
        domain = request.POST.get('domain')
        schema = request.POST.get('schema')
        name = request.POST.get('name')
        description = request.POST.get('description')
    
        client=Client()
        client.domain_url=domain
        client.schema_name=schema
        client.name=name
        client.description=description
        client.save()