#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
себе.