在 Django 的 DetailView 中将表单字段设置为对象 ID
Posted
技术标签:
【中文标题】在 Django 的 DetailView 中将表单字段设置为对象 ID【英文标题】:Setting a form field to the object id in Django's DetailView 【发布时间】:2020-11-13 09:41:13 【问题描述】:让我用一些代码来解释我的问题: 我正在编写一个简单的博客应用程序。我有一个 Post ListView,它列出了博客帖子(显然),还有一个 DetailView,它显示了所选帖子的内容。 DetailView 使用默认关键字 object 来引用 DetailView 中显示的帖子实例。每篇博文的末尾都有一个评论部分。
在 forms.py 我有一个 CommentForm 类:
class CommentForm(ModelForm):
class Meta:
model = Comment
fields = ['author_nickname', 'content']
在 models.py 中我有一个 Comment 模型:
class Comment(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
author_nickname = models.CharField(max_length=10)
date_posted = models.DateTimeField(auto_now_add= True)
content = models.TextField(max_length=90)
post = models.ForeignKey(Post,on_delete=models.CASCADE)
我使用一个DetailView来显示选中帖子的内容,但是由于它还有一个用于将cmets添加到评论部分的表单,所以它继承自DetailView和FormView,如下所示:
class PostDetailView(DetailView, FormView):
model = Post
form_class = CommentForm
success_url = '/thanks/'
def form_valid(self, form):
form.save()
return super().form_valid(form)
现在,问题来了:我希望 CommentForm 向 DetailView 显示的帖子添加评论,表单所在的位置(显然)。我在 DetailView 模板的末尾添加了表单标签。它就住在这里:
<form method="POST">
% csrf_token %
form.as_p
<button type="submit" class="btn btn-primary">Add</button>
</form>
显然,当我提交此表单时,我收到一条错误消息,因为缺少 Post_id。如果我将 Post 字段添加到 forms.py 中的 CommentForm 类,如下所示:
fields = ['author_nickname', 'content', 'post']
然后手动指定帖子并点击提交,表单可以正常工作,并正确添加评论而没有错误(出于开发目的,它当前将用户导航到 /thanks/) 那么,如何在表单中指定 post_id 字段而不显示该字段?我尝试在 DetailView 模板的表单标签之间添加类似的内容:
<input type="hidden" name="post_id" value="object.id">
但它不起作用,我仍然得到错误:
NOT NULL 约束失败:blog_comment.post_id
谁能帮帮我? :(我的手被绑了:c 我不知道如何解决这个问题。我不知道如何访问 views.py 中的对象实例,因此设置初始字段值对我没有帮助。
请帮忙:
【问题讨论】:
【参考方案1】:最好将其设为CreateView
[Django-doc],然后自己将Post
对象传递给上下文,例如:
from django.shortcuts import get_object_or_404
class PostDetailView(CreateView):
model = Comment
form_class = CommentForm
success_url = '/thanks/'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
obj = get_object_or_404(Post, pk=self.kwargs['pk'])
context['object'] = context['post'] = obj
return context
def form_valid(self, form):
form.instance.post_id = self.kwargs['pk']
return super().form_valid(form)
在这里,如果表单有效,我们将post_id
设置为URL中传递的pk
,然后让CreateView
进一步处理逻辑。这将保存表单,并重定向到success_url
。
【讨论】:
【参考方案2】:我创造了这样的东西:
from django.views.generic.edit import FormMixin
class PostDetailView(FormMixin, DetailView):
model = Post
template_name = 'blog/post_detail.html'
context_object_name = 'post'
form_class = CommentForm
在 get_context_data 中,我初始化表单,并在其中指出 initial='post': self.object
的帖子
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.instance.author = self.request.user
form.instance.post = self.get_object()
form.save()
return super(PostDetailView, self).form_valid(form)
def get_success_url(self):
return reverse('post_detail', kwargs='slug': self.object.slug)
【讨论】:
以上是关于在 Django 的 DetailView 中将表单字段设置为对象 ID的主要内容,如果未能解决你的问题,请参考以下文章
在 splitviewcontroller 中将数组从 masterview 发送到 detailview
Django - DetailView 中的 DateTimeField