bernardopires / django-tenant-schemas

Tenant support for Django using PostgreSQL schemas.
https://django-tenant-schemas.readthedocs.org/en/latest/
MIT License
1.45k stars 425 forks source link

Losing queryset after exiting tenant_context #507

Open Andreypnfrv opened 6 years ago

Andreypnfrv commented 6 years ago

I was getting one tenant data in other tenant and faced this problem:

with tenant_context(tenant):
      queryset = Model.objects.all()
      print(queryset)     # returns normal queryset
print(queryset)     # returns empty queryset

Any ideas how to repair this?

I made this workaround:

with tenant_context(tenant):
      queryset = Model.objects.all()
      object_list = [i for i in queryset]
print(object_list)     # returns objects

But it doesn't help when i need to return a queryset object...


class TenantQueryset(object):

    model = None
    queryset = None

    def __init__(self, base_queryset):
        self.model = base_queryset.model
        queryset = set()
        for item in base_queryset:
            queryset.add(item)
        self.queryset = queryset

    def __iter__(self):
        for item in self.queryset:
            yield item

with tenant_context(tenant):
      queryset = TenantQueryset(simple_queryset)
print(queryset)       # returns objects

This works better. But it doesn't seem elegant solution to me. And this also does not work with such things as getting objects from ManyToManyFields

farhah commented 6 years ago

Have you found the workarounds?

farhah commented 6 years ago

I ended up doing this for 1 data query

import pickle
print(connection.schema_name)  # public
pickle_qs = None
with tenant_context(tenant):
   # tenant is non public
    qs = MyModel.objects.filter(pk=pk)
    pickle_qs = pickle.dumps(qs)
q = pickle.loads(pickle_qs)
print(connection.schema_name)  # connection is public but we get a queryset from non public tenant
return q # non public queryset

Is it efficient?

Or this for multiple data

qs = None
with tenant_context(tenant):
    qs = list(MyModel.objects.all())
return qs

list actually hit the db https://docs.djangoproject.com/en/1.11/ref/models/querysets/#when-querysets-are-evaluated

fproldan commented 4 years ago

I am stuck with the same problem.

I understand that queryset are lazy, so I going with the list(qs) approach until now (though @Andreypnfrv approach seems nicer).

The problem I'm facing is there I need concatenate querysets from various tenants in one queryset ir order to aggregate information to show in a data table. This must to be a queryset instead of a list.

I guess there isn't possible.