Как отобразить только суперпользователей в поле ManyToManyField при создании экземпляра на странице администратора

У нас есть эта модель:

# models.py

from django.conf import settings
User = settings.AUTH_USER_MODEL

class Category(models.Model):
    ...
    users = models.ManyToManyField(User, help_text='Choose Superusers only', blank=True)  

Вопросы следующие:
при создании экземпляра на admin странице, как я могу заставить форму отображать superusers только при множественном выборе?

Для этого необходимо настроить форму, используемую на странице администрирования для создания экземпляров модели Category. Вы можете переопределить метод formfield_for_manytomany класса ModelAdmin, чтобы отфильтровать набор запросов поля users и включить в него только суперпользователей. Вот как это можно сделать:

# admin.py

from django.contrib import admin
from .models import Category
from django.contrib.auth.models import User

class CategoryAdmin(admin.ModelAdmin):
    def formfield_for_manytomany(self, db_field, request, **kwargs):
        if db_field.name == "users":
            kwargs["queryset"] = User.objects.filter(is_superuser=True)
        return super().formfield_for_manytomany(db_field, request, **kwargs)

admin.site.register(Category, CategoryAdmin)

Учитывая, что в справочном тексте говорится, что вы хотите выбрать только суперпользователей, вы, вероятно, хотите отфильтровать всех ModelForm, то есть тех, кто находится в ModelAdmin, а также (возможно) будущих ModelForm.

Простой способ сделать это - использовать limit_choices_to=… параметр [Django-doc]. Это позволит отфильтровать QuerySet, которые он предложит форме для этого поля, а также выполнить соответствующую валидацию:

from django.conf import settings


class Category(models.Model):
    # …
    users = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        help_text='Choose Superusers only',
        blank=True,
        limit_choices_to={'is_superuser': True},
    )

Таким образом, он будет автоматически работать на ModelAdmin, поскольку использует ModelForm за шторками, а также на всех "ванильных" Django ModelForm и, вероятно, на большинстве пакетов Django, плагинов и т.д.

Вернуться на верх