Форммиксин в детальном представлении Django

#python #django

Вопрос:

Я хотел, чтобы раздел комментариев был на той же странице, что и в моем детальном представлении, поэтому я решил использовать FormMixin для добавления комментариев. Это не вызывает никаких ошибок, но отправленные комментарии, похоже, никуда не денутся, и они также не отображаются на сайте администратора.

models.py

 from django.db import models
from django.utils import timezone
from django.urls import reverse
from embed_video.fields import EmbedVideoField
from django.contrib.auth.models import User

class Post(models.Model):
    title = models.CharField(max_length = 100)
    content = models.TextField()
    video = EmbedVideoField()
    date_posted = models.DateTimeField(default = timezone.now)
    author = models.ForeignKey(User, on_delete = models.CASCADE)

    def __str__(self):
        return self.title

    def get_absolute_url(self):
       return reverse('post-detail', kwargs={'pk': self.pk})

class PostComment(models.Model):
    post = models.ForeignKey(Post, related_name='comments', on_delete = models.CASCADE)
    author = models.ForeignKey(User, on_delete = models.CASCADE)
    date_posted = models.DateTimeField(default = timezone.now)
    body = models.TextField()

    def __str__(self):
        return f'{self.post} - {self.author}'
 

forms.py

 from django import forms
from django.forms import ModelForm
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit, Fieldset, Button, Layout, Div, ButtonHolder, Field, Reset
from .models import Post, PostComment
from crispy_forms.bootstrap import FormActions
from django.urls import reverse

class CommentForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_method = 'POST'
        self.fields['body'].required = True
        self.fields['body'].label = False
        self.helper.layout = Layout(
            Field('body', style='max-height: 90px', placeholder='Write a comment...'),
            ButtonHolder(
                Submit('submit', 'Post', css_class='m-2 ms-3'),
                Reset('Reset This Form', 'Cancel', css_class='btn btn-secondary')
            ),
        )

    class Meta:
        model = PostComment
        fields = ['body','post',]
 

views.py
В основном я почерпнул это из документации django.

 from django.shortcuts import render
from django.views.generic import (
    ListView,
    DetailView,
    CreateView,
    UpdateView,
    DeleteView
)
from .models import Post, PostComment
from .forms import PostCreateForm, CommentForm
from django.views.generic.edit import FormMixin

class PostDetailView(FormMixin, DetailView):
    model = Post
    context_object_name = 'posts'
    form_class = CommentForm

    def get_success_url(self):
        return reverse('post-detail', kwargs={'pk': self.object.id})

    def get_context_data(self, **kwargs):
        context = super(PostDetailView, self).get_context_data(**kwargs)
        context['form'] = CommentForm(initial={'post': self.object})
        return context

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        form = self.get_form()
        if form.is_valid():
            return self.form_valid(form)
        else:
            return self.form_invalid(form)

    def form_valid(self, form):
        form.save()
        return super(PostDetailView, self).form_valid(form)
 

urls.py

 urlpatterns = [
    path('', PostListView.as_view(), name = 'home-home'),
    path('post/new/', PostCreateView.as_view(), name = 'post-create'),
    path('post/<int:pk>/', PostDetailView.as_view(), name = 'post-detail'),
]
 

post_detail.html

 {% extends 'videosite/base.html' %}
{% load crispy_forms_tags %}
{% load embed_video_tags %}
{% block body %}

<div class="container mt-5">
    <div class="card border-dark">
        <div class="row row-cols-2 gutter-0">
            <div class="col-7 pe-0" style="height: 526px;">
                <div class="card-body border-end border-dark">
                    <div class="embed-responsive embed-responsive-16by9">
                        {% video posts.video '720x490' %}
                    </div>
                </div>
            </div>
            <div class="col-5 ps-0" style="height: 526px;">
                <div class="card-body bg-light" style="height: 526px;">
                    {% for comment in posts.comments.all %}
                        <a class="h5 text-dark text-decoration-none me-5" href="#"> {{ comment.author }}</a>
                        <span class="ms-3" >{{ comment.date_posted|date:"F d, Y" }}</span>
                        <p class="card-text">{{ comment.body }} </p>
                    {% endfor %}
                </div>
                    {% csrf_token %}
                    {% crispy form %}
            </div>
            <div class="col-7 pe-0" >
                <div class="card-body border-top border-end border-dark">
                    <h5><a class="fw-bold text-dark text-decoration-none" href="#">{{ posts.title }}</a></h5>
                    <p class="card-text">{{ posts.content }}</p>
                </div>
                <div class="card-body border-end border-dark" >
                    <span class="text-muted text-decoration-none">Posted by <a class="text-muted" href="#"> {{ posts.author }}</a> </span>
                    <span class="ms-3 text-muted" >{{ posts.date_posted|date:"F d, Y" }}</span>
                </div>
            </div>
        </div>
    </div>
</div>

{% endblock body %}
 

Комментарии:

1. Можете ли вы показать нам PostDetailView код, связанный с шаблоном?

2. Ах да, извините, теперь это отредактировано.

3. Как только вы захотите обработать форму, создайте подкласс FormView.

Ответ №1:

Используйте FormView не DetailView в качестве базового класса. Я ожидаю, что тогда все это сработает.

Бесценным ресурсом являются классные представления на основе классов. Это показывает, что DetailView у этого нет обработчика СООБЩЕНИЙ (метода), и это FormMixin тоже не обеспечивает этого, и, вероятно, поэтому то, что у вас есть, не работает.

Обработка СООБЩЕНИЙ определяется сама по FormView себе.