Скажем, у меня есть сайт, где Пользователи могут добавить Записи через панель администрации. У каждого Пользователя есть своя собственная Категория, он ответственен за (каждой Категории присвоили Редактор через ForeingKey/ManyToManyField).
Когда Пользователь добавляет Запись, я ограничиваю выбор при помощи EntryAdmin как это:
class EntryAdmin(admin.ModelAdmin):
(...)
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == 'category':
if request.user.is_superuser:
kwargs['queryset'] = Category.objects.all()
else:
kwargs['queryset'] = Category.objects.filter(editors=request.user)
return db_field.formfield(**kwargs)
return super(EntryAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
Таким образом, я могу ограничить категории, к которым Пользователь может добавить Запись, и она работает прекрасная.
Теперь хитрая часть: На Записи changelist/action страница я хочу показать только те Записи, которые принадлежат Категории текущего Пользователя. Я пытался сделать это использование этого метода:
def changelist_view(self, request, extra_context=None):
if not request.user.is_superuser:
self.queryset = self.queryset.filter(editors=request.user)
Но я получаю эту ошибку:
AttributeError: 'функциональный' объект не имеет никакого атрибута 'фильтр'
Это странно, потому что я думал, что это должен быть типичный QuerySet. В основном такие методы не хорошо документируются, и роющий через тонны кода Django не мой любимый спорт.
Какие-либо идеи, как я могу достигнуть своей цели?
queryset
- это метод на ModelAdmin
, который возвращает queryset. Вам нужно переопределить его в классе EntryAdmin
.
def queryset(self, request):
qs = super(EntryAdmin, self).queryset(request)
if request.user.is_superuser:
return qs
else:
return qs.filter(editors=request.user)
Изменение набора запросов ограничит количество записей, отображаемых в представлении списка. Вам также необходимо переопределить has_change_permission
, чтобы убедиться, что пользователь имеет разрешение на редактирование объекта на странице редактирования отдельного объекта. Более подробную информацию смотрите в следующем сообщении блога Джеймса Беннета: