【问题标题】:Django: WARNING - Method Not Allowed (POST)Django:警告-不允许的方法(POST)
【发布时间】:2020-08-28 11:16:58
【问题描述】:

我知道上面的错误是什么意思。发布时似乎我无法处理表格。我可以在基于函数的视图中做到这一点,但在基于类的视图中我有点迷失了。

我正在创建一个评论应用程序,这是forms.py 应用程序中的forms.py 内容:

class CommentForm(forms.Form):
    content_type = forms.CharField(widget=forms.HiddenInput)
    object_id = forms.CharField(widget=forms.HiddenInput)
    body = forms.CharField(widget=forms.Textarea)

然后在博客应用的DetailView,我是这样处理的:

class BlogDetail(DetailView):
    model = Blog
    template_name = 'blogs/blog_detail.html'
    context_object_name = 'blog'

    def get_object(self):
        blog_slug = self.kwargs.get('blog_slug')
        return get_object_or_404(Blog, slug=blog_slug)

    def get_context_data(self, *args, **kwargs):
        obj = self.get_object()
        context = super().get_context_data(**kwargs)
        context['comments'] = Comment.objects.filter_by_instance(obj)

        """ comment form """
        initial_data = {
            'content_type': obj.get_content_type,
            'object_id': obj.id
        }
        if self.request.method == 'POST':
            form = CommentForm(self.request.POST, initial=initial_data)
            if form.is_valid():
                c_type = form.cleaned_data.get('content_type')
                content_type = ContentType.objects.get(model=c_type)
                object_id = form.cleaned_data.get('object_id')
                body = form.cleaned_data.get('body')
                new_comment, created = Comment.objects.get_or_create(
                    user=self.request.user,
                    content_type=content_type,
                    object_id=object_id,
                    body=body
                )
        else: 
            form = CommentForm(initial=initial_data)

        context['comment_form'] = form

        return context

虽然我通过了form = CommentForm(self.request.POST, initial=initial_data),但听起来有问题,有人可以帮忙吗?谢谢

编辑:

class BlogDetail(DetailView, FormView):
    model = Blog
    template_name = 'blogs/blog_detail.html'
    context_object_name = 'blog'
    form_class = CommentForm

    def get_object(self):
        blog_slug = self.kwargs.get('blog_slug')
        return get_object_or_404(Blog, slug=blog_slug)

    def get_initial(self):
        obj = self.get_object()
        return {
            'content_type': obj.get_content_type,
            'object_id': obj.id
        }

    def form_valid(self, form):
        c_type = form.cleaned_data.get('content_type')
        content_type = ContentType.objects.get(model=c_type)
        object_id = form.cleaned_data.get('object_id')
        body = form.cleaned_data.get('body')

        Comment.objects.create(
            user=self.request.user,
            content_type=content_type,
            object_id=object_id,
            body=body
        )

编辑 2:

谁能发现这种方法的错误:

class BlogDetail(DetailView):
    model = Blog
    template_name = 'blogs/blog_detail.html'
    context_object_name = 'blog'
    form_class = CommentForm

    def get_object(self):
        blog_slug = self.kwargs.get('blog_slug')
        return get_object_or_404(Blog, slug=blog_slug)

    def get(self, request, *args, **kwargs):
        obj = self.get_object()

        initial_data = {
            'content_type': obj.get_content_type,
            'object_id': obj.id
        }
        print("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa", obj.get_content_type)
        form = self.form_class(initial=initial_data)

        return render(request, self.template_name, {'form': form})

    def post(self, request, *args, **kwargs):
        form = self.form_class(request.POST)

        if form.is_valid():
            c_type = form.cleaned_data.get('content_type')
            content_type_2 = ContentType.objects.get(model=c_type)
            object_id = form.cleaned_data.get('object_id')
            body = form.cleaned_data.get('body')

            Comment.objects.create(
                user=request.user,
                content_type=content_type_2,
                object_id=object_id,
                body=body,
            )

        return render(request, self.template_name, {'form': form})

【问题讨论】:

  • 永远不要合并两个视图。如果要为详细视图添加表单支持,请添加 FormMixin,而不是 FormView。再三考虑,您不需要详细视图。可以通过在get_context_data中调用get_object()来解决对象的渲染...
  • 请提供答案,或查看我的第二种方法,为什么它在我的情况下不起作用。

标签: python django django-views


【解决方案1】:

帖子由基于类的视图的post 方法处理:

class BlogDetail(DetailView):
    # ...
    def post(self, request, *args, **kwargs):
        # all your form processing

Django 附带了几个视图,它们已经为表单处理过程提供了各种钩子,例如FormView,你可以利用它:

class BlogDetail(DetailView, FormView):
    form_class = CommentForm

    def form_valid(self, form):
        c_type = form.cleaned_data.get('content_type')
        # ...

    def get_initial(self):
        obj = self.get_object()
        return {
            'content_type': obj.get_content_type,
            'object_id': obj.id
        }

    # ....

默认情况下,表单作为"form" 传递到上下文中。

【讨论】:

  • 感谢您的帮助,请参阅已编辑的问题。我错过了一些东西
【解决方案2】:

要允许您的视图发布请求,请编写一个函数def post(self, request, *args, **kwargs),它将接收发布请求。如果您想像处理 get 一样处理它,请将其重定向到 get 函数

def post(self, request, *args, **kwargs):
    return self.get(request, *args, **kwargs)

【讨论】:

  • 谢谢,我试过了,但在我的情况下不起作用。你能看看我的问题吗?我编辑并使用了你这里说的方法。
  • ContentType matching query does not exist 你看到编辑了吗?我在基于类的视图中使用了 get 和 post 方法
  • 你不应该把obj.get_content_type称为obj.get_content_type()吗?
  • 上面写着'ContentType' object is not callable。我想也许它与数据库有关。我删除了数据库并重新制作,结果相同
【解决方案3】:

您不需要DetailView。您可以简单地使用 CreateView。我认为您已经正确覆盖了所有内容以便能够放弃 DetailView,除了 get_form_kwargs()。

不过……

我通常以不同的方式处理此问题,因为它令人困惑且非常 hacky。相反,您通过 get_context_data() 将表单添加到 DetailView,然后在模板中发布到 /blog/{id}/comment/create,在那里您有 CreateView。这让事情变得简单多了。

【讨论】:

  • 我需要DetailView 来显示博客的详细信息,所以我必须保留它,我想学习而不必发表评论CreateView 如何在一个简单的@ 中做到这一点987654325@上课。你能看看我的第二个编辑问题吗?我在那里使用post 方法来处理这种情况。谢谢你的帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-16
  • 2021-04-05
  • 2018-05-30
  • 2019-07-05
  • 1970-01-01
  • 2022-01-23
  • 1970-01-01
相关资源
最近更新 更多