Как использовать запрос в ModelForm в Django
Я хотел бы сделать запрос, где текущий пользователь используется как фильтр в ModelForm:
class BookSubmitForm(ModelForm):
book = forms.ModelChoiceField(queryset=Book.objects.filter(owner=request.user),)
...
Проводит ли Django запрос в форму? Это хорошая практика? Как я могу использовать запрос? (конечно, запрос имени не определен)
Edit:
Я попробовал другое решение, которое должно вызвать форму в представлении, передав ей запрос:
form = BookSubmitForm(request)
а затем в форме я использую это:
class BookSubmitForm(ModelForm):
def __init__(self, request, *args, **kwargs):
super(BookSubmitForm, self).__init__(*args, **kwargs)
self.fields["library"].queryset = Library.objects.filter(owner=request.user)
Он работает, и код находится в форме. Теперь я не уверен, что это лучшее решение, можно ли улучшить его?
Ответы
Ответ 1
Нет, запрос не передается в ModelForm. Вам нужно сделать что-то вроде этого на ваш взгляд:
form = BookSubmitForm()
form.fields['book'].queryset = Book.objects.filter(owner=request.user)
# pass form to template, etc
Как вы сказали, часто бывает проще инкапсулировать это в объекте Form, особенно если у вас есть несколько полей, которые потребуют отфильтрованных запросов. Чтобы сделать это, переопределите формы __init__()
и пусть он принимает значение kwarg request
:
class BookSubmitForm(ModelForm):
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request")
super(BookSubmitForm, self).__init__(*args, **kwargs)
self.fields["book"].queryset = Book.objects.filter(owner=self.request.user)
self.fields["whatever"].queryset = WhateverModel.objects.filter(user=self.request.user)
Затем просто передайте запрос всякий раз, когда вы создаете BookSubmitForm
в своем представлении:
def book_submit(request):
if request.method == "POST":
form = BookSubmitForm(request.POST, request=request)
# do whatever
else:
form = BookSubmitForm(request=request)
# render form, etc
Ответ 2
Расширение ответа AdamKG на представления на основе классов - переопределите метод get_form_kwargs
:
class PassRequestToFormViewMixin:
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['request'] = self.request
return kwargs
from django.views.generic.edit import CreateView
class BookSubmitCreateView(PassRequestToFormViewMixin, CreateView):
form_class = BookSubmitForm
# same for EditView
а затем в формах:
from django.forms import ModelForm
class BookSubmitForm(ModelForm):
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request")
super().__init__(*args, **kwargs)
...