django-admin-interface icon indicating copy to clipboard operation
django-admin-interface copied to clipboard

Multi tenancy support

Open kennylajara opened this issue 1 year ago • 4 comments

Hi! Thank you amazing package!

Now, for the want to use different themes based on the Django site being visited.

I know this is currently not supported. But I'm opening this ticked because I saw someone asked the same in this Issue and when you asked if he is using Django Sites, you suggested it could be easy if he is using it. Unfortunately, he wasn't said no. As I am using it, it would be awesome nice to find a solution or workaround.

kennylajara avatar May 07 '24 11:05 kennylajara

@kennylajara as explained in #242, it should be relatively easy to achieve this by:

  1. extending ThemeQuerySet
  2. overriding get_active method (here you decide the theme to return)
  3. setting the customized queryset as default objects manager for the Theme model.

If you will come back with a reusable solution I will be glad to look at it!

fabiocaccamo avatar May 07 '24 12:05 fabiocaccamo

I can think on using something like this to determine if the Site framework is being used:

from django.conf import settings

def is_sites_app_installed():
    if 'django.contrib.sites' in settings.INSTALLED_APPS:
        try:
            from django.contrib.sites.models import Site
            return True
        except ImportError:
            return False
    return False

Extend the Theme model to add this property:

    site = models.PositiveSmallIntegerField(  # it can be a FK too
        blank=True,
        default=1,
        verbose_name=_("site"),
    )

And change the QuerySet to this:

class ThemeQuerySet(models.QuerySet):
    def get_active(self):
        using_sites_framework = is_sites_app_installed()

        if using_sites_framework:
            objs_active_qs = self.filter(active=True, site=Site.objects.get_current().id)  # `Site.objects.get_current()` is `site` is a FK
        else:
            objs_active_qs = self.filter(active=True)

        objs_active_ls = list(objs_active_qs)
        objs_active_count = len(objs_active_ls)

        if objs_active_count == 0:
            obj = self.all().first()
            if obj:
                obj.set_active()
            else:
                obj = self.create()

        elif objs_active_count == 1:
            obj = objs_active_ls[0]

        elif objs_active_count > 1:
            obj = objs_active_ls[-1]
            obj.set_active()

        return obj

But I think it will still require a way to handle sites that are added and have not set any Theme yet. It might be a way to mark a theme as default or something else.

kennylajara avatar May 07 '24 14:05 kennylajara

Would that work for you? I really need this feature, so, I'm willing to develop it with you guidance.

kennylajara avatar May 07 '24 19:05 kennylajara

@kennylajara it's hard to give help based on code snippets pasted here, I would suggest you to work on your own solution that works well for your use case and that is enough generic to fit other people needs, then submit a PR.

fabiocaccamo avatar May 10 '24 10:05 fabiocaccamo