Django CreateView get_context_context_data не передает дополнительный объект в шаблон
Я создаю приложение для форума на django. Пользователь может ответить на тему, нажав кнопку. При этом пользователь переходит на новую страницу, содержащую форму с текстовым полем для ввода ответа. PK темы, на которую отвечают, передается ему по url и сохраняется как parent_post ответа в CreateView.
Это все работает хорошо (пока...), но я также хочу отображать название темы, на которую отвечают, в верхней части страницы, но я не могу использовать этот переданный в pk параметр для отображения названия темы в верхней части html-страницы.
УРЛЫ:
path('reply/<int:pk>/', NewReplyView.as_view(), name='new-reply'),
Вид:
class NewReplyView(generic.CreateView):
form_class = NewReplyForm
initial = {'key': 'value'}
template_name = 'forum_app/new_reply.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['x'] = "hahaaha"
p = Post.objects.get(pk=self.kwargs.get('pk')) # Why does this not work, seems to work in the def post() method
context['thread'] = p
return context
def get(self, request, *args, **kwargs):
form = self.form_class(initial=self.initial)
return render(request, self.template_name, {'form':form})
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
submission = form.save(commit=False)
submission.author = request.user
submission.parent_post = Post.objects.get(pk=self.kwargs.get('pk'))
submission.save()
#return redirect(to='/') # TODO: redirect to newly created thread
return redirect(reverse('forum_app:thread-detail', kwargs={'pk': self.kwargs['pk']}))
#return redirect(reverse_lazy('forum_app:thread-list'))
return render(request, self.template_name, {'form': form})
Шаблон:
{% extends 'base.html'%}
{% block breadcrumb %}
<li class="breadcrumb-item"><a href="{% url 'home' %}">Home</a></li>
<li class="breadcrumb-item"><a href="{% url 'forum_app:thread-list' %}">Threads</a></li>
<li class="breadcrumb-item active" aria-current="New Reply">New Reply</li>
{% endblock %}
<p>{{thread.post_title}}</p>
{% block content %}
<h5>Reply to thread: {{x}}</h5>
<form method='POST'>
{% csrf_token%}
{{form}}
<button class="btn-outline-primary btn-lg" name="submit_post" type="submit">Submit</button>
</form>
{% endblock %}
Я даже попробовал вставить в контекст случайную строку, но это не сработало, что-то вроде этого:
class ThreadDetailView(generic.DetailView):
context_object_name = "post"
queryset = Post.objects.all()
template_name = 'forum_app/thread_detail.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['replies'] = Post.objects.filter(parent_post=self.object)
context['c'] = "hahag"
return context
В этом примере "хахаг", переданный в контекст, работает. Я могу просто поместить <p>{{c}}</p>
в верхнюю часть шаблона, и он появится.
Проблема в том, как вы обрабатываете запрос get. Вы только отображаете форму без передачи дополнительного контекста... (Единственное, что доступно в вашем контексте - это форма и дополнительные вещи, передаваемые контекстными процессорами, такие как запрос, пользователь...) CBV - это довольно сложно. Вы должны знать, какой метод переопределить, и во многих случаях вы должны вызвать родительский метод с помощью super(), чтобы сохранить поток (не всегда так).
Сначала удалите этот блок кода
def get(self, request, *args, **kwargs):
form = self.form_class(initial=self.initial)
return render(request, self.template_name, {'form':form})
Для передачи начальных значений используйте
def get_initial(self):
initial=super().get_initial()
initial.update({'key': 'value'})
return initial
То же самое для метода post переопределите метод form_valid вместо этого
def form_valid(self, form):
submission=form.instance
submission.author = request.user
submission.parent_post = Post.objects.get(pk=self.kwargs.get('pk'))
return super().form_valid(form)
Для перенаправления после успешной отправки формы вы можете либо установить success_url с помощью reverse_lazy, либо переопределить метод get_success_url:
Новый CreateView полностью можно переписать так
class NewReplyView(generic.CreateView):
form_class = NewReplyForm
initial = {"key": "value"}
template_name = "forum_app/new_reply.html"
success_url = reverse_lazy('namespace:url-name')#For simple urls
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["x"] = "hahaaha"
p = Post.objects.get(
pk=self.kwargs.get("pk")
) # Why does this not work, seems to work in the def post() method
context["thread"] = p
return context
def get_initial(self):
initial=super().get_initial()
initial.update({'key': 'value'})
return initial
def form_valid(self, form):
submission=form.instance
submission.author = request.user
submission.parent_post = Post.objects.get(pk=self.kwargs.get('pk'))
return super().form_valid(form)
def get_success_url(self):#OR use this if complex url pattern or to perform some logic before redirect
return reverse('namespace:url-name', kwargs={'pk': self.object.pk})