Главная Документация Руководство разработчика модулей Работа с данными основной системы

Поиск

Релиз

Содержание

Нужна помощь?

Не нашли ответ на свой вопрос? Свяжитесь с нашей службой поддержки.

Обратиться в поддержку

Работа с данными основной системы

Обновлено: 07 Декабрь 2025 Версия: 2.2

Модули могут взаимодействовать с данными основной системы двумя способами:

  1. Через API - для чтения данных с защитой от изменений в моделях
  2. Напрямую через модели - для сложных операций, записи данных и использования методов моделей

Рекомендация: Используйте API для чтения данных, если хотите защитить модуль от изменений в моделях. Используйте прямые импорты для сложных запросов, методов моделей и операций записи.

Когда использовать API

Используйте API в следующих случаях:

  1. Чтение данных - для получения информации о сущностях системы (сотрудники, задачи, проекты и т.д.)
  2. Защита от изменений - когда хотите защитить модуль от изменений во внутренней структуре моделей
  3. Стандартизированный интерфейс - когда нужен единый способ работы с данными

Преимущества API:

  • Абстракция от внутренней структуры моделей
  • Защита от изменений в моделях (API может оставаться совместимым)
  • Стандартизированный интерфейс
  • Безопасность через систему прав доступа Django

Ограничения API:

  • Только чтение данных (read-only)
  • Ограниченный набор полей (только те, что в сериализаторе)
  • Нет доступа к методам моделей
  • Нет возможности создавать/изменять/удалять объекты

Когда напрямую обращаться к моделям

Используйте прямые импорты моделей в следующих случаях:

  1. Создание/изменение/удаление объектов - API предоставляет только чтение
  2. Сложные запросы - когда нужны сложные фильтры, аннотации, агрегации
  3. Использование методов моделей - когда нужно вызвать методы объектов (например, get_absolute_url(), save() с дополнительной логикой)
  4. Связанные объекты - когда нужен доступ к связанным объектам через ForeignKey/ManyToMany
  5. Транзакции - когда нужны атомарные операции с несколькими объектами
  6. Производительность - когда нужны оптимизированные запросы с select_related(), prefetch_related()

Преимущества прямого доступа:

  • Полный доступ ко всем полям и методам моделей
  • Возможность создания, изменения и удаления объектов
  • Сложные запросы с использованием Django ORM
  • Использование методов моделей и менеджеров
  • Транзакции и атомарные операции

Важно:

  • При прямом доступе к моделям вы работаете с внутренней структурой системы
  • Изменения в моделях основной системы могут повлиять на ваш модуль
  • Всегда проверяйте права доступа перед операциями записи

Примеры использования

Пример 1: Получение списка сотрудников через API

import requests
from django.conf import settings

def get_employees_via_api(request):
    """Получение сотрудников через API"""
    response = requests.get(
        f'{settings.BASE_URL}/modules/api/core/employees/',
        cookies=request.COOKIES  # Используем сессию пользователя
    )
    if response.status_code == 200:
        employees = response.json()
        return employees
    return []

Пример 2: Получение списка сотрудников напрямую через модели

from personal.models import Employee

def get_employees_direct():
    """Получение сотрудников напрямую через модели"""
    # Простой запрос
    employees = Employee.objects.filter(status='working')

    # Сложный запрос с оптимизацией
    employees = Employee.objects.select_related('manager', 'org').filter(
        status='working',
        org__name__icontains='Отдел'
    ).order_by('last_name', 'first_name')

    return employees

Пример 3: Создание задачи (только через модели)

from tasks.models import Task
from personal.models import Employee
from django.utils import timezone
from datetime import timedelta

def create_task_for_employee(employee_id, title, description):
    """Создание задачи - только через модели, так как API read-only"""
    employee = Employee.objects.get(id=employee_id)

    task = Task.objects.create(
        title=title,
        description=description,
        executor=employee,
        author=employee,  # или текущий пользователь
        duedate=timezone.now() + timedelta(days=7),
        completed=False
    )

    return task

Пример 4: Сложный запрос с агрегацией (только через модели)

from tasks.models import Task
from django.db.models import Count, Q, Avg
from django.utils import timezone
from datetime import timedelta

def get_task_statistics(employee_id):
    """Получение статистики по задачам - сложный запрос через модели"""
    now = timezone.now()
    week_ago = now - timedelta(days=7)

    stats = Task.objects.filter(executor_id=employee_id).aggregate(
        total=Count('id'),
        completed=Count('id', filter=Q(completed=True)),
        overdue=Count('id', filter=Q(completed=False, duedate__lt=now)),
        due_soon=Count('id', filter=Q(
            completed=False,
            duedate__gte=now,
            duedate__lte=now + timedelta(days=3)
        )),
        avg_progress=Avg('progress')
    )

    return stats

Пример 5: Использование методов модели (только через модели)

from tasks.models import Task
from notifications.services import send_notify

def notify_about_task(task_id):
    """Отправка уведомления о задаче - используем методы модели"""
    task = Task.objects.get(id=task_id)

    # Используем метод get_absolute_url() модели
    task_url = task.get_absolute_url()

    # Используем связанные объекты
    executor = task.executor
    if executor and executor.user:
        send_notify(
            obj=task,
            recipients=[executor.user],
            template_name='module_code_TaskNotification',
            extra_context={
                'task_url': task_url,
                'executor_name': executor.display_name
            }
        )

Пример 6: Транзакция с несколькими объектами (только через модели)

from tasks.models import Task
from django.db import transaction
from personal.models import Employee

@transaction.atomic
def create_tasks_for_team(team_member_ids, title_template):
    """Создание задач для команды - атомарная операция"""
    tasks = []
    for member_id in team_member_ids:
        employee = Employee.objects.get(id=member_id)
        task = Task.objects.create(
            title=f"{title_template} - {employee.display_name}",
            executor=employee,
            # ... другие поля
        )
        tasks.append(task)

    # Если произойдет ошибка, все изменения откатятся
    return tasks

Пример 7: Работа с ForeignKey и ManyToMany (только через модели)

from tasks.models import Task
from projects.models import Project

def get_project_tasks(project_id):
    """Получение задач проекта с оптимизацией"""
    # Используем select_related для ForeignKey
    tasks = Task.objects.select_related(
        'executor',
        'author',
        'project'
    ).filter(project_id=project_id)

    # Для ManyToMany используем prefetch_related
    # (если бы у Task было поле ManyToMany)

    return tasks

Рекомендации по выбору подхода

Используйте API, если:

  • ✅ Нужно только чтение данных
  • ✅ Хотите защитить модуль от изменений в моделях
  • ✅ Нужна стандартизированная интеграция
  • ✅ Достаточно полей, предоставляемых API

Используйте прямые импорты моделей, если:

  • ✅ Нужно создавать/изменять/удалять объекты
  • ✅ Нужны сложные запросы с агрегациями
  • ✅ Нужно использовать методы моделей
  • ✅ Нужны оптимизированные запросы (select_related, prefetch_related)
  • ✅ Нужны транзакции
  • ✅ Нужен доступ ко всем полям модели

Импорт моделей основной системы

При прямом доступе к моделям используйте полные пути импорта:

# Сотрудники
from personal.models import Employee, Organigram

# Пользователи
from users.models import CustomUser, CustomGroup

# Задачи
from tasks.models import Task, TaskSource

# Проекты
from projects.models import Project, ProjectRole, ProjectType

# Заявки
from servicedesk.requests import Request

# Договоры
from finance.contracts import Contract

# Уведомления
from system.notifications import Notification
from notifications.services import send_notify

# Клиенты
from clients.models import Clients

Важно:

  • Всегда проверяйте наличие прав доступа перед операциями записи
  • Используйте get_object_or_404() для безопасного получения объектов
  • Используйте транзакции для атомарных операций
  • Оптимизируйте запросы с помощью select_related() и prefetch_related()