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})
Вернуться на верх