Как можно добавить динамически создаваемые таблицы в административную панель?

Привет всем! 

У меня есть Django-сервис, который предназначен для внутренних нужд нашей компании, и мы планируем предоставить доступ к нему другим организациям. Для этого я работаю над созданием демо-аккаунта, чтобы пользователи могли опробовать функционал. Я задумался, как лучше организовать демо-доступ для пользователей. 

В качестве решения я решил присвоить каждому демо-пользователю уникальный ID и динамически создавать персонализированные модели и таблицы для каждого аккаунта. Например, для моделей `organisation` и `employee` у нас будут создаваться `demo12345_organisation` и `demo12345_employee`. 

С технической стороны у меня нет проблем с созданием этих моделей и их использованием. Однако я не могу понять, как зарегистрировать эти таблицы в админ-панели так, чтобы для пользователя с ID 12345 отображались только таблицы с соответствующим префиксом. 

Может быть, я не совсем правильно подхожу к организации демо-доступа? Каковы ваши мысли по этому поводу?
  • 16 октября 2024 г. 14:32
Ответы на вопрос 2
Создание динамически создаваемых моделей и таблиц в Django — это довольно сложная задача, особенно когда речь идет о регистрации этих моделей в админ-панели. Основной подход заключается в том, чтобы управлять доступом к данным, а не создавать отдельные таблицы для каждого пользователя. Вот несколько рекомендаций и шагов, которые вы можете рассмотреть:

### 1. Использование одной модели с динамическими полями

Вместо создания отдельных таблиц для каждого демо-пользователя, вы можете использовать одну модель с дополнительным полем, которое будет идентифицировать принадлежность данных к конкретному демо-аккаунту. Например, можно добавить поле `account_id`, которое будет указывать на конкретный демо-аккаунт или организацию.

```python
class Organisation(models.Model):
    account_id = models.CharField(max_length=255)
    name = models.CharField(max_length=255)
    # другие поля

class Employee(models.Model):
    account_id = models.CharField(max_length=255)
    name = models.CharField(max_length=255)
    organisation = models.ForeignKey(Organisation, on_delete=models.CASCADE)
    # другие поля
```

### 2. Настройка фильтрации в админ-панели

Вы можете переопределить метод `get_queryset` в админ-интерфейсе, чтобы отображать только те объекты, которые принадлежат текущему демо-аккаунту:

```python
from django.contrib import admin

class OrganisationAdmin(admin.ModelAdmin):
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        if request.user.is_authenticated:
            # Получите идентификатор текущего демо-аккаунта
            account_id = request.user.account_id
            return qs.filter(account_id=account_id)
        return qs.none()

admin.site.register(Organisation, OrganisationAdmin)

class EmployeeAdmin(admin.ModelAdmin):
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        if request.user.is_authenticated:
            account_id = request.user.account_id
            return qs.filter(account_id=account_id)
        return qs.none()

admin.site.register(Employee, EmployeeAdmin)
```

### 3. Применение Permissions и Groups

Если вы всё же хотите разрабатывать отдельные модели, то стоит использовать группы и права доступа в Django для определения, какой пользователь или группа пользователей имеет доступ к какой модели.

### 4. Альтернативные подходы

Если ваша архитектура предполагает много таких динамических моделей, можно рассмотреть использование библиотек для управления версиями схем (как например, Django Dynamic Models) или NoSQL решений, где структура данных более гибкая.

### 5. Разработка, Документация и Тестирование

Не забудьте документировать ваше решение и thoroughly протестировать его, чтобы убедиться, что система безопасности надёжна, а данные каждого демо-аккаунта находятся в недоступности для других пользователей.

### Заключение

Хотя создание отдельных таблиц для каждого пользователя возможно, это может привести к избыточной сложности и нелогичному управлению данными. Использование одной модели с фильтрацией и идентификатором аккаунта гораздо более эффективно и масштабируемо.
Остановился на том, чтобы каждому демо-пользователю присваивать уникальный ID и динамически создавать модели и таблицы персональные под аккаунт.

Зачем такие сложности? Достаточно добавить в каждую модель поле tenant и при выборке записей фильтровать по значению этого поля.
Похожие вопросы