Отправка данных из представления Django в форму Django
У меня есть представление Django, и я хочу отправить данные запроса на форму.
class PostDetailView(DetailView):
model = Post
form = CommentForm
def get_form_kwargs(self):
kwargs = super(PostDetailView, self).get_form_kwargs()
kwargs['user'] = self.request.user.username
return kwargs
def post(self, request, *args, **kwargs):
form = CommentForm(request.POST)
if form.is_valid():
post = self.get_object()
form.instance.user = request.user
form.instance.post = post
form.save()
return redirect(reverse("post-detail", args=[post.pk]))
from django import forms
from .models import Comment
from djrichtextfield.widgets import RichTextWidget
class CommentForm(forms.ModelForm):
user = forms.ChoiceField(required=True)
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
super(CommentForm, self).__init__(*args, **kwargs)
self.fields['user'].choices = self.user
content = forms.CharField(widget=RichTextWidget(attrs={
'class': 'md-textarea form-control',
'placeholder': 'Comment here ...',
'rows': '4',
}))
class Meta:
model = Comment
fields = ('author', 'content',)
Согласно документации, get_form_kwargs позволяет задавать пары ключ-значение в kwargs. Затем эти kwargs передаются в форму. Функция формы init должна быть способна подхватить значение пользователя из kwargs.
Однако, self.user возвращает None, и отладка показала, что get_form_kwargs вообще не выполняется.
У меня два вопроса: как выполняются функции в классах представления? И какой правильный метод передачи данных из представления в форму?
В документации это явно не описано, но get_form_kwargs
срабатывает только при наличии CreateView
или UpdateView
.
В вашем случае вы можете использовать UpdateView
, а затем использовать form_valid
для выполнения пост-процесса. Но обратите внимание, что нам нужно удалить kwargs['instance']
, потому что по умолчанию это представление будет думать, что мы работаем с объектом Post
, когда на самом деле это Comment
:
Попробуйте с этим:
class PostDetailView(UpdateView):
model = Post
form = CommentForm
def get_form_kwargs(self):
kwargs = super(PostDetailView, self).get_form_kwargs()
# Remove the post object as instance,
# since we are working with a comment
kwargs.pop('instance', None)
kwargs['user'] = self.request.user.username
return kwargs
def form_valid(self, form):
instance = form.save(commit=False)
instance.user = self.request.user
instance.post = self.get_object() # returns the post
instance.save()
return redirect(reverse("post-detail", args=[post.pk]))
или, если вы не хотите использовать UpdateView
(не рекомендуется), вы можете просто явно вызвать get_form_kwargs
при построении формы. Однако вы не можете вызвать super().get_form_kwargs()
, поскольку, как уже говорилось, родительский класс не имеет этого метода:
class PostDetailView(DetailView):
model = Post
form = CommentForm
def get_form_kwargs(self):
kwargs = {'user': self.request.user.username}
return kwargs
def post(self, request, *args, **kwargs):
form = CommentForm(request.POST, **self.get_form_kwargs())
if form.is_valid():
post = self.get_object()
form.instance.user = request.user
form.instance.post = post
form.save()
return redirect(reverse("post-detail", args=[post.pk]))
И последнее, подумайте о переименовании этого класса, поскольку мы работаем с добавлением комментария к посту, а не с "деталями поста", поэтому что-то вроде PostAddCommentView
?