python - Django form.is_valid() 失败的基于类的视图 - Form、SingleObject、DetailMixins
问题描述
我有两个应用程序,在这里我们将它们称为博客和评论。
评论有一个评论模型。博客有一个博客模型。评论有一个评论表单。博客有一个 DetailView。
我希望我的 CommentForm 出现在 Blog DetailView 上,因此人们可以从博客详细信息页面提交评论。
表单呈现正常 - 它发出一个 POST 请求,它重定向到 get_success_url() 但是(我在views.py中添加了一些打印 - 见下文)在views.py中进行测试以查看是否收到了表单数据我看到 form.is_valid() 路径不符合,我不明白为什么。
我基本上是在尝试遵循“替代更好的解决方案”: https ://docs.djangoproject.com/en/2.2/topics/class-based-views/mixins/#using-formmixin-with-detailview
博客/views.py
class CommentLooker(SingleObjectMixin, FormView):
template_name = 'blogs/blog_detail.html'
form_class = CommentForm
model = blog
def get_object(self):
#self.team = get_object_or_404(team, team_id=self.kwargs['team_id'])
#queryset_list = blog.objects.filter(team = self.team)
team_id_ = self.kwargs.get("team_id")
blog_id_ = self.kwargs.get("blog_id")
return get_object_or_404(blog, blog_id=blog_id_, team=team_id_)
def post(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return HttpResponseForbidden()
self.object = self.get_object()
return super(CommentLooker, self).post(request, *args, **kwargs)
def get_success_url(self):
return reverse('blogs:teams')
class blogDisplay(View):
def get(self,request,*args,**kwargs):
view = blogFromteamContentView.as_view()
return view(request, *args, **kwargs)
def post(self,request,*args,**kwargs):
view = CommentLooker.as_view()
return view(request,*args,**kwargs)
class blogFromteamContentView(LoginRequiredMixin, DetailView):
model = blog
template_name = 'blogs/blog_detail.html'
# override get_object so we can use blog_id when we use this class in urls.py
# otherwise DetailViews expect 'pk' which defaults to the primary key of the model.
def get_object(self):
team_id_ = self.kwargs.get("team_id")
blog_id_ = self.kwargs.get("blog_id")
return get_object_or_404(blog, blog_id=blog_id_, team=team_id_)
def get_context_data(self, **kwargs):
context = super(blogFromteamContentView, self).get_context_data(**kwargs)
team_id_ = self.kwargs.get("team_id")
blog_id_ = self.kwargs.get("blog_id")
# get the list of blogs for a given blog id and team id combination.
context['queryset'] = get_object_or_404(blog, blog_id=blog_id_, team=team_id_)
# get and set things related to ability to associate comments to a blog.
initial_data = {
"content_type": blog.get_content_type,
"object_id": blog.blog_id
}
comments = blog.comments # uses the @property set in this class.
comment_form = CommentForm(self.request.POST or None, initial=initial_data)
if comment_form.is_valid():
print(comment_form.cleaned_data)
else:
print('invalido!')
context['comment_form'] = comment_form
return context
博客/models.py
class Blog(models.Model):
team= models.ForeignKey(Team, on_delete=CASCADE)
blog_id = models.AutoField(primary_key=True)
blog_name = models.CharField(
max_length=100, verbose_name='Blog Name')
博客/urls.py
path('teams/<int:team_id>/blogs/<int:blog_id>/', blog.blogDisplay.as_view(), name='detail'),
blog_detail.html
<div>
<p class="lead"> Comments </p>
<form method="POST" action="."> {% csrf_token %}
{{ comment_form}}
<input type="submit" value="Post Comment" class="btn btn-primary">
</form>
<hr/>
{% for comment in blog.comments.all %}
<blockquote class="blockquote">
<p>{{ comment.content }}</p>
<footer class="blockquote-footer"> {{ comment.user }} | {{ comment.timestamp|timesince }} ago </footer>
</blockquote>
<hr/>
{% endfor %}
评论/forms.py
从 django 导入表格
class CommentForm(forms.Form):
content_type = forms.CharField(widget=forms.HiddenInput)
object_id = forms.IntegerField(widget=forms.HiddenInput)
parent_id = forms.IntegerField(widget=forms.HiddenInput, required=False)
content = forms.CharField(widget=forms.Textarea)
编辑:
使用 print(comment_form.errors) 后:
建议我的 initial_data 可能是问题所在。事实上,我的 initial_data 中的 content_type 和 object_id 都是问题。我要的是 blog.blog_id - 即使用类,而不是实例。所以我改变了
获取上下文数据:
def get_context_data(self, **kwargs):
context = super(blogFromteamContentView, self).get_context_data(**kwargs)
team_id_ = self.kwargs.get("team_id")
blog_id_ = self.kwargs.get("blog_id")
# get the list of blogs for a given blog id and team id combination.
context['queryset_list_recs'] = get_object_or_404(blog, blog_id=blog_id_, team=team_id_)
instance = get_object_or_404(blog, blog_id=blog_id_, team=team_id_)
initial_data = {
"content_type": instance.get_content_type,
"object_id": blog_id_
}
和我的views.py:
def post(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return HttpResponseForbidden()
self.object = self.get_object()
comment_form = CommentForm(self.request.POST)
if comment_form.is_valid():
print('valido')
c_type = comment_form.cleaned_data.get("content_type")
content_type = ContentType.objects.get(model=c_type)
obj_id = comment_form.cleaned_data.get('object_id')
content_data = comment_form.cleaned_data.get("content")
new_comment, created = Comment.objects.get_or_create(
user = self.request.user,
content_type = content_type,
object_id = obj_id,
content = content_data
)
else:
print('postinvalido!')
return super(CommentLooker, self).post(request, *args, **kwargs)
这(不适当的打印语句除外)现在似乎给出了预期的行为。
解决方案
使用 print(comment_form.errors) 后:
- object_id
- 项目清单
输入一个整数。
建议我的 initial_data 可能是问题所在。事实上,我的 initial_data 中的 content_type 和 object_id 都是问题。我要的是 blog.blog_id - 即使用类,而不是实例。所以我改变了
获取上下文数据:
def get_context_data(self, **kwargs):
context = super(blogFromteamContentView, self).get_context_data(**kwargs)
team_id_ = self.kwargs.get("team_id")
blog_id_ = self.kwargs.get("blog_id")
# get the list of blogs for a given blog id and team id combination.
context['queryset_list_recs'] = get_object_or_404(blog, blog_id=blog_id_, team=team_id_)
instance = get_object_or_404(blog, blog_id=blog_id_, team=team_id_)
initial_data = {
"content_type": instance.get_content_type,
"object_id": blog_id_
}
和我的views.py:
def post(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return HttpResponseForbidden()
self.object = self.get_object()
comment_form = CommentForm(self.request.POST)
if comment_form.is_valid():
print('valido')
c_type = comment_form.cleaned_data.get("content_type")
content_type = ContentType.objects.get(model=c_type)
obj_id = comment_form.cleaned_data.get('object_id')
content_data = comment_form.cleaned_data.get("content")
new_comment, created = Comment.objects.get_or_create(
user = self.request.user,
content_type = content_type,
object_id = obj_id,
content = content_data
)
else:
print('postinvalido!')
return super(CommentLooker, self).post(request, *args, **kwargs)
这(不适当的打印语句除外)现在似乎给出了预期的行为。我不清楚为什么需要在 post 方法中创建 CommentForm 的实例 - 感觉就像我在这里做错了什么。
推荐阅读
- bash - Bash 将命令输出与字符串进行比较
- spring-boot - 我如何在spring cloud config中从另一个属性文件中引用一个属性文件
- android - 片段之间的滚动效果实际上不允许用户滚动?
- java - 如何使用流为 hashmap 实现 isEmpty()?
- loops - Ansible:遍历字典列表 - 循环与 with_items
- django - 图片不在 django 中提供
- c# - Web (ASP.Net) Wcf:未找到从桌面客户端连接时出错
- python - Pandas 基于 2 列删除重复项,有时会颠倒
- php - 有没有办法使用 PHP 表单循环浏览数据库中的多个记录?
- java - 我是否正确使用了 Scanner 和 File 类?