Python Django form.is_valid()失败的基于类的视图-表单、SingleObject、DetailMixins

Python Django form.is_valid()失败的基于类的视图-表单、SingleObject、DetailMixins,python,django,django-forms,Python,Django,Django Forms,我有两个应用程序,这里我们称它们为博客和评论 注释有一个注释模型。博客有一个博客模型。评论有一个评论表单。博客有一个详细视图 我希望我的评论表单显示在“博客详细信息”视图中,以便人们可以从博客详细信息页面提交评论 表单呈现正常-它发出POST请求,它重定向以获取_success_url(),但是(我在views.py中添加了几个打印项-请参见下文)在views.py中进行测试以查看是否收到表单数据,我看到表单。is_valid()路径未满足,我不明白原因 我基本上是在尝试遵循这个“替代更好的解决

我有两个应用程序,这里我们称它们为博客和评论

注释有一个注释模型。博客有一个博客模型。评论有一个评论表单。博客有一个详细视图

我希望我的评论表单显示在“博客详细信息”视图中,以便人们可以从博客详细信息页面提交评论

表单呈现正常-它发出POST请求,它重定向以获取_success_url(),但是(我在views.py中添加了几个打印项-请参见下文)在views.py中进行测试以查看是否收到表单数据,我看到表单。is_valid()路径未满足,我不明白原因

我基本上是在尝试遵循这个“替代更好的解决方案”:

blog/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
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')
path('teams/<int:team_id>/blogs/<int:blog_id>/', blog.blogDisplay.as_view(), name='detail'),
blog/models.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
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')
path('teams/<int:team_id>/blogs/<int:blog_id>/', blog.blogDisplay.as_view(), name='detail'),
blog/url.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
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')
path('teams/<int:team_id>/blogs/<int:blog_id>/', blog.blogDisplay.as_view(), name='detail'),
编辑:

使用打印后(注释表单错误):
  • 对象id
  • 输入一个整数。
  • 问题可能在于我的初始数据。事实上,我的初始数据中的内容类型和对象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_
        }
    
    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)
    
    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_
        }
    
    和我的视图。py:

    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_
        }
    
    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)
    
    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_
        }
    
    这(不适当的打印语句除外)现在似乎给出了预期的行为。

    使用打印后(注释形式错误):

    • 对象id
    • 列表项
    输入一个整数

    问题可能在于我的初始数据。事实上,我的初始数据中的内容类型和对象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_
        }
    
    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)
    
    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_
        }
    
    对于我的视图.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的实例-感觉我在这里做错了什么。

    我想你的意思是如果comment\u form.is\u valid():在
    blogFromteamContentView.get\u context\u data
    中没有找到行
    ?在一篇文章中,你使用的是
    CommentLooker
    视图,而不是该视图。当然,我真傻。非常感谢。我将重点介绍CommentLooker的post方法。我不确定post是如何获取其上下文的——也就是说,我将在这里保存表单。因此,如果我定义初始数据并将
    comment\u form=CommentForm(self.request.post,None,initial=initial\u data)
    添加到
    CommentLooker
    的post方法中,则注释表单将失败
    comment\u form。是否有效()
    刚才我的假设是,有一些错误使我的表单无效-一旦修复了,我会在CommentLooker的post方法中添加'Comment.objects.get_或'u create([fields]),以保存注释。
    print(form.errors)
    给我:
    • object\u id
      • 输入一个整数。
    ,所以我想问题在于我的初始数据。我将在主体中编辑一个澄清。主体问题文本已更新为近似的解决方案。我不确定是否要在CommentLooker的POST方法中实例化CommentForm(self.request.POST)。表格不是已经传进来了吗?我不清楚如何访问它。