Django:在通用 DetailView 中实现表单
Django: Implementing a Form within a generic DetailView
在浏览了几个 google 搜索结果页面后,我仍然绝望地陷入同样的问题。我正在尝试在博客 post 下实现一个评论字段。我感谢任何提示和建议!
我正在用 Django 开发一个博客,它设置了第一个通用的 ListView 来简要显示所有可用的博客 post 和第二个通用的 DetailView 来显示特定的博客 post 更详细。我现在想在特定博客 post 下方放置一个 add_comment_field,并在下方显示所有其他评论。当评论表单显示在单独的页面上但与 DetailView 不在同一页面上时,它会起作用,这是期望的结果。
我怀疑这与 views.py 和 forms.py 之间的相互作用有关,但我无法找出问题所在。
再次感谢您的帮助!
views.py
from django.shortcuts import render, get_object_or_404, redirect
from .models import Post, Comment
from .forms import CommentForm
from django.views.generic.detail import DetailView
class ParticularPost(DetailView):
template_name='blog/post.html'
model = Post
def add_comment_to_post(self, pk):
post = get_object_or_404(Post, pk=pk)
if self.method == "POST":
form = CommentForm(self.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.save()
return redirect('post_detail', pk=post.pk)
else:
form = CommentForm()
return {'form': form}
urls.py
from django.conf.urls import url, include
from django.views.generic import ListView, DetailView
from .models import Post, Comment
from .views import ParticularPost
urlpatterns = [
url(r'^$', ListView.as_view(queryset=Post.objects.all().order_by("-date")[:25], template_name="blog/blog.html")),
url(r'^(?P<pk>\d+)$', ParticularPost.as_view(), name="post_detail"),
]
post.html
{% extends "personal/header.html" %}
{% load staticfiles %}
{% block content %}
<div class="container-fluid background_design2 ">
<div class="header_spacing"></div>
<div class="container post_spacing">
<div class="row background_design1 blog_post_spacing inline-headers">
<h3><a href="/blog/{{post.id}}">{{ post.title }}</a></h3>
<h6> on {{ post.date }}</h6>
<div class = "blog_text">
{{ post.body|safe|linebreaks}}
</div>
<br><br>
</div>
<div>
<form method="POST" class="post-form">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Send</button>
</form>
</div>
<div class=" row post_spacing background_design1 ">
<hr>
{% for comment in post.comments.all %}
<div class=" col-md-12 comment">
<div class="date">{{ comment.created_date }}</div>
<strong>{{ comment.author }}</strong>
<p>{{ comment.text|linebreaks }}</p>
</div>
{% empty %}
<p>No comments here yet :(</p>
{% endfor %}
</div>
</div>
</div>
{% endblock %}
forms.py
from django import forms
from .models import Comment
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('author', 'text',)
models.py
from django.db import models
from django.utils import timezone
class Post(models.Model):
title = models.CharField(max_length=140)
body = models.TextField()
date = models.DateTimeField()
def __str__(self):
return self.title
class Comment(models.Model):
post = models.ForeignKey('blog.Post', related_name='comments')
author = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.text
如果要组合 DetailView
和一个表格,请使用 FormMixin
:
from django.shortcuts import render, get_object_or_404, redirect
from django.views.generic.detail import DetailView
from django.views.generic.edit import FormMixin
from django.urls import reverse
from .models import Post, Comment
from .forms import CommentForm
class ParticularPost(FormMixin, DetailView):
template_name='blog/post.html'
model = Post
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(ParticularPost, 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(ParticularPost, self).form_valid(form)
并且不要忘记将 post
字段添加到表单中(您可以隐藏它):
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('author', 'text', 'post',)
添加创建日期的更好方法 - 使用 auto_now_add=True
:
created_date = models.DateTimeField(auto_now_add=True)
没有必要用首字母填充表格。我将扩展上述解决方案。
def form_valid(self, form):
post = self.get_object()
myform = form.save(commit=False)
myform.post = post
form.save()
return super(ParticularPost, self).form_valid(form)
有没有办法在用户添加评论后隐藏表单?这适用于通过传递变量(例如 new_comment = True)并在模板中使用 if 子句的基于函数的视图。但似乎无法弄清楚基于 class 的视图。即使您在 form_valid() 函数中将变量设置为 true,表单仍会弹出。
在浏览了几个 google 搜索结果页面后,我仍然绝望地陷入同样的问题。我正在尝试在博客 post 下实现一个评论字段。我感谢任何提示和建议!
我正在用 Django 开发一个博客,它设置了第一个通用的 ListView 来简要显示所有可用的博客 post 和第二个通用的 DetailView 来显示特定的博客 post 更详细。我现在想在特定博客 post 下方放置一个 add_comment_field,并在下方显示所有其他评论。当评论表单显示在单独的页面上但与 DetailView 不在同一页面上时,它会起作用,这是期望的结果。
我怀疑这与 views.py 和 forms.py 之间的相互作用有关,但我无法找出问题所在。
再次感谢您的帮助!
views.py
from django.shortcuts import render, get_object_or_404, redirect
from .models import Post, Comment
from .forms import CommentForm
from django.views.generic.detail import DetailView
class ParticularPost(DetailView):
template_name='blog/post.html'
model = Post
def add_comment_to_post(self, pk):
post = get_object_or_404(Post, pk=pk)
if self.method == "POST":
form = CommentForm(self.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.save()
return redirect('post_detail', pk=post.pk)
else:
form = CommentForm()
return {'form': form}
urls.py
from django.conf.urls import url, include
from django.views.generic import ListView, DetailView
from .models import Post, Comment
from .views import ParticularPost
urlpatterns = [
url(r'^$', ListView.as_view(queryset=Post.objects.all().order_by("-date")[:25], template_name="blog/blog.html")),
url(r'^(?P<pk>\d+)$', ParticularPost.as_view(), name="post_detail"),
]
post.html
{% extends "personal/header.html" %}
{% load staticfiles %}
{% block content %}
<div class="container-fluid background_design2 ">
<div class="header_spacing"></div>
<div class="container post_spacing">
<div class="row background_design1 blog_post_spacing inline-headers">
<h3><a href="/blog/{{post.id}}">{{ post.title }}</a></h3>
<h6> on {{ post.date }}</h6>
<div class = "blog_text">
{{ post.body|safe|linebreaks}}
</div>
<br><br>
</div>
<div>
<form method="POST" class="post-form">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Send</button>
</form>
</div>
<div class=" row post_spacing background_design1 ">
<hr>
{% for comment in post.comments.all %}
<div class=" col-md-12 comment">
<div class="date">{{ comment.created_date }}</div>
<strong>{{ comment.author }}</strong>
<p>{{ comment.text|linebreaks }}</p>
</div>
{% empty %}
<p>No comments here yet :(</p>
{% endfor %}
</div>
</div>
</div>
{% endblock %}
forms.py
from django import forms
from .models import Comment
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('author', 'text',)
models.py
from django.db import models
from django.utils import timezone
class Post(models.Model):
title = models.CharField(max_length=140)
body = models.TextField()
date = models.DateTimeField()
def __str__(self):
return self.title
class Comment(models.Model):
post = models.ForeignKey('blog.Post', related_name='comments')
author = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.text
如果要组合 DetailView
和一个表格,请使用 FormMixin
:
from django.shortcuts import render, get_object_or_404, redirect
from django.views.generic.detail import DetailView
from django.views.generic.edit import FormMixin
from django.urls import reverse
from .models import Post, Comment
from .forms import CommentForm
class ParticularPost(FormMixin, DetailView):
template_name='blog/post.html'
model = Post
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(ParticularPost, 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(ParticularPost, self).form_valid(form)
并且不要忘记将 post
字段添加到表单中(您可以隐藏它):
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('author', 'text', 'post',)
添加创建日期的更好方法 - 使用 auto_now_add=True
:
created_date = models.DateTimeField(auto_now_add=True)
没有必要用首字母填充表格。我将扩展上述解决方案。
def form_valid(self, form):
post = self.get_object()
myform = form.save(commit=False)
myform.post = post
form.save()
return super(ParticularPost, self).form_valid(form)
有没有办法在用户添加评论后隐藏表单?这适用于通过传递变量(例如 new_comment = True)并在模板中使用 if 子句的基于函数的视图。但似乎无法弄清楚基于 class 的视图。即使您在 form_valid() 函数中将变量设置为 true,表单仍会弹出。