Ограничение выбора внешних ключей Django ModelForm в зависимости от request.user

Иногда желательно ограничить выбор, представленный полем ForeignKey в ModelForm, чтобы пользователи не видели содержимое друг друга. Однако это может быть непросто, поскольку модели не имеют доступа к request.user.

Рассмотрим приложение с двумя моделями:

class Folder(models.Model):
    user = models.ForeignKey(get_user_model(), editable=False, on_delete=models.CASCADE)
    name = models.CharField(max_length=30)

class Content(models.Model):
    folder = models.ForeignKey(Folder, on_delete=models.CASCADE)
    text = models.CharField(max_length=50)

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

и.д.:

Content.folder.user == request.user

QUESTION: Как мы можем использовать, например, CreateView, чтобы при создании нового контента пользователям показывался выбор только их собственных папок?

Я делаю это, переопределяя CreateView.get_form_class(), чтобы изменить атрибуты соответствующего поля формы, прежде чем оно будет передано остальной части представления.

Метод по умолчанию, унаследованный от views.generic.edit.ModelFormMixin, возвращает ModelForm, которая представляет все редактируемые поля модели в словаре base_fields. Таким образом, это хорошее место для внесения любых желаемых изменений, а также имеет доступ к self.request.user.

Так, для приведенного выше примера, в файле views.py мы могли бы сказать:

class ContentCreateView(LoginRequiredMixin, CreateView):
    model = Content
    fields = '__all__'

    def get_form_class(self):
        modelform = super().get_form_class()
        modelform.base_fields['folder'].limit_choices_to = {'user': self.request.user}
        return modelform

Читайте больше о ForeignKey.limit_choices_to в docs.

Обратите внимание, что выбор полей обеспечивается валидацией формы, так что это должно быть достаточно надежно.

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