Ограничение выбора внешних ключей 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.
Обратите внимание, что выбор полей обеспечивается валидацией формы, так что это должно быть достаточно надежно.