Пытаемся отфильтровать поле "менеджеры", чтобы оно показывало только менеджеров в отделе пользователя, вошедшего в систему в данный момент

У меня есть 3 модели

  • Базовая модель пользователя, которую предоставляет Django

  • UserProfile, модель, которая имеет 2 поля: поле внешнего ключа с таблицей пользователей поле department, которое является полем выбора с выпадающим меню, каждый пользователь имеет 1 отдел

    .

И, наконец, модель данных, содержащая поле Manager, во многом совпадающее с моделью пользователя.

Модели

class Data(models.Model):
"""Model representing each event's data."""
title = models.CharField(max_length=200)
description = models.TextField(max_length = 2000)
managers = models.ManyToManyField(User, related_name = "event_co_manager_user", blank=True)

class UserProfile(models.Model):
"""Model representing the user profile"""
user = models.OneToOneField(User, on_delete=models.CASCADE)
DEPARTMENT_CHOICES = (
    (0, 'Dep1'),
    (1, 'Dep2'),
    (2, 'Dep3'),
)

department = models.PositiveSmallIntegerField(choices=DEPARTMENT_CHOICES, null=True)

Я пытаюсь отфильтровать поле менеджера на бэкенде, чтобы показывать только менеджеров, которые работают в одном отделе, поскольку мы не хотим, чтобы люди могли добавлять другие отделы в качестве менеджеров в свои события

Вот функция, которую я пытаюсь перезаписать в моем admin.py (использую Django 5.0)

def formfield_for_manytomany(self, db_field, request, **kwargs):
if db_field.name == "managers":
            kwargs["queryset"] = Data.objects.filter(managers.userprofile.department ==                          request.user.userprofile.department)

return super().formfield_for_manytomany(db_field, request, **kwargs)

Я продолжаю получать ошибки о том, что поле managers не имеет атрибута userprofile

Когда вы хотите построить запрос, который будет расширять отношения, например, когда вы хотите отфильтровать по атрибуту ForeignKey, вам нужно использовать dunder вместо period для доступа к этим отношениям.

Заменить:

Data.objects.filter(managers.userprofile.department ==

с:

Data.objects.filter(managers__userprofile__department ==

Вы можете установить queryset с помощью:

def formfield_for_manytomany(self, db_field, request, **kwargs):
    if db_field.name == 'managers':
        kwargs['queryset'] = Data.objects.filter(
            managers__userprofile__department=request.user.userprofile.department
        )

    return super().formfield_for_manytomany(db_field, request, **kwargs)

but this will make an extra query to get the .userprofile of the request.user. Additionally using choices=… [Django-doc] for something that can "grow" is often not a good idea.

Обычно используется дополнительная модель, например:

class Data(models.Model):
    "Model representing each event's data."
    title = models.CharField(max_length=200)
    description = models.TextField(max_length=2000)
    managers = models.ManyToManyField(
        User, related_name='event_co_manager_user', blank=True
    )


class Department(models.Model):
    name = models.CharField(max_length=128, unique=True)

    def __str__(self):
        return self.name


class UserProfile(models.Model):
    'Model representing the user profile'
    user = models.OneToOneField(User, on_delete=models.CASCADE)

    department = models.ForeignKey(
        Department,
        on_delete=models.PROTECT,
        related_name='userprofiles',
        null=True,
    )

Тогда это выглядит так:

def formfield_for_manytomany(self, db_field, request, **kwargs):
    if db_field.name == 'managers':
        kwargs['queryset'] = Data.objects.filter(
            managers__userprofile__department__userprofile__user=request.user
        )

    return super().formfield_for_manytomany(db_field, request, **kwargs)
Вернуться на верх