【问题标题】:Django using generic views, error http 405Django 使用通用视图,错误 http 405
【发布时间】:2019-02-27 10:55:52
【问题描述】:

我正在尝试对 CRUD 使用 django 通用视图,但 DeleteView 导致错误 405,遵循官方 Django https://docs.djangoproject.com/en/2.1/ref/class-based-views/generic-editing/ 指南,我不明白我的错误在哪里,所以这是我的代码:

views.py

from django.urls import reverse
from django.views.generic import (
    CreateView,
    DetailView,
    ListView,
    UpdateView,
    ListView,
    DeleteView
)

from .forms import ContatoModelForm
from .models import Contato
class ContatoCreateView(CreateView):
    template_name = 'contato/contato_create.html'
    form_class = ContatoModelForm
    model = Contato

class ContatoListView(ListView):
    template_name = 'contato/contato_list.html'
    model = Contato

class ContatoDetailView(DetailView):
    template_name = 'contato/contato_detail.html'
    model = Contato

class ContatoUpdateView(UpdateView):
    template_name = 'contato/contato_create.html'
    form_class = ContatoModelForm
    model = Contato

class ContatoDeleteView(DeleteView):
    template_name = 'contato/contato_delete.html'
    model = Contato
    def get_success_url(self):
        return reverse('contato:contato-list')

urls.py

 from django.urls import path
 from .views import (
     ContatoCreateView,
     ContatoDeleteView,
     ContatoDetailView,
     ContatoListView,
     ContatoUpdateView,
)
app_name = 'contato'
urlpatterns = [
    path('', ContatoListView.as_view(), name='contato-list'),
    path('create/', ContatoCreateView.as_view(), name='contato-create'),
    path('<int:pk>/', ContatoDetailView.as_view(), name='contato-detail'),
    path('<int:pk>/update/', ContatoUpdateView.as_view(), name='contato-update'),
    path('<int:pk>/delete/', ContatoDeleteView.as_view(), name='contato-delete'),
]

contato_delete.html

<form action='.' method='post'>{% csrf_token %}
<dialog class="mdl-dialog">
    <h6>Deseja excluir {{ object.nome }}?</h6>
    <div class="mdl-dialog__actions">
        <input type="submit" class="mdl-button mdl-js-button mdl-button--accent" value="Excluir">
        <button type="button" class="mdl-button close">Cancelar</button>
    </div>
</dialog>
</form>

contato_detail.html

{% extends 'base.html' %}
{% load staticfiles %}

{% block content %}
<div class="mdl-card__title">
    <h2 class="mdl-card__title-text">{{ object.nome }}</h2>
</div>
<div class="mdl-layout-spacer"></div>
<a id="show-dialog"  class="mdl-button mdl-js-button mdl-button--icon">
  <i class="material-icons">delete</i>
</a>

{% include "contato/contato_delete.html" %}

<script type="text/javascript" src="{% static 'js/dialog.js' %}"></script>

<div class="mdl-card__actions mdl-card--border">
    <ul class="demo-list-icon mdl-list">

        <li class="mdl-list__item">
            <span class="mdl-list__item-primary-content">
    <i class="material-icons mdl-list__item-icon">call</i>
    {{ object.celular }}
  </span>
        </li>

        <li class="mdl-list__item">
            <span class="mdl-list__item-primary-content">
    <i class="material-icons mdl-list__item-icon">email</i>
    {{ object.email }}
  </span>
        </li>
        <li class="mdl-list__item">
            <span class="mdl-list__item-primary-content">
    <i class="material-icons mdl-list__item-icon">business</i>
    {{ object.cargo }} na {{ object.empresa}}
  </span>
        </li>
    </ul>

</div>

<a href="{% url 'contato:contato-update' object.id %}" id="fab" class="mdl-button mdl-js-button mdl-button--fab mdl-button--primary">
     <i class="material-icons">create</i>
    </a>

{% endblock %}

contato_list.html

 {% extends "base.html" %}
 {% block content %}
 <style>
  .demo-list-three {
    width: 800px;
    margin-left: 30px;
  }
  #fab {
    position: fixed;
    display: block;
    right: 0;
    bottom: 0;
    margin-right: 40px;
    margin-bottom: 40px;
    z-index: 900;
  }
</style>

<form method='GET' action=''>
</form>
{% for obj in object_list %}
<ul class="demo-list-three mdl-list">
  <li class="mdl-list__item mdl-list__item--three-line">
    <span class="mdl-list__item-primary-content">
        <i class="material-icons mdl-list__item-avatar">person</i>
        <a href='{{ obj.get_absolute_url }}'><span>{{ obj.nome }}</span> 
 </a>
    <span class="mdl-list__item-text-body">
          {{ obj.celular }} <br>
          {{ obj.email }}
         </span>
    </span>

    <a href="{{ obj.get_absolute_url }}" class="mdl-button mdl-js-button mdl-button--primary">
  DETALHES
</a>
  </li>
</ul>
 {% endfor %}

 <a href="{% url 'contato:contato-create' %}" id="fab" class="mdl-button mdl-js-button mdl-button--fab mdl-button--primary">
     <i class="material-icons">person_add</i>
    </a>


 {% endblock content %}

【问题讨论】:

  • 405,真的吗? 404 似乎更合理
  • 是的,是 405 方法不允许
  • 为什么要在每个 CBV 中定义 get_object?您只需定义model = MyModel,并让CBV 处理它。这就是文档中的内容。
  • 然后在您的 CreateView 中使用:queryset = Contato.objects.all() 为什么?您正在尝试创建一个新对象,而不是检索它的列表。

标签: django http-status-code-405


【解决方案1】:

您需要在表单上设置action 以匹配删除contato 对象的路由(url)。

基本上把&lt;form&gt;的打开标签改成:

<form action='{{ id }}/delete' method='post'>

并通过contextid 传递给视图,如下所示:

class ContatoDetailView(DetailView):
    model = Contato
    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        context = self.get_context_data(object=self.object)
        context['id'] = self.object.id
        return self.render_to_response(context)

作为额外的建议,我会考虑让您的路线更加 RESTful。有关信息,请参阅此要点:https://gist.github.com/alexpchin/09939db6f81d654af06b。不过需要注意的是 HTML5 表单不支持删除(或放置)请求。要使用表单发出删除请求,您必须在提交时使用 javascript 手动提交请求。

【讨论】:

  • 如何在我的方法中使用通用视图传递上下文? @henrywoody
  • 现在缺少 QuerySet,你想看看我的 views.py 完整吗? @henrywoody
  • @PatrickAmaral 您是否为ContatoDetailView 定义了model?如果没有,请尝试在 class ContatoDetailView(DetailView): 正下方添加行 model = Contato
  • 好的,返回Generic detail view ContatoDetailView must be called with either an object pk or a slug in the URLconf.。需要在课外使用这些方法吗? @henrywoody
  • @PatrickAmaral 尝试将urls.py 中的路由声明中的&lt;int:id&gt; 更改为&lt;int:pk&gt;
【解决方案2】:

简化您的代码:

class ContatoCreateView(CreateView):
    template_name = 'contato/contato_create.html'
    form_class = ContatoModelForm
    model = Contato # Tell the CBV what object you will create

    #** This doesn't make any sense, you are creating a new Contato not retrieving a queryset.
    # queryset = Contato.objects.all() 

    #** Let the ModelForm handle the validation
    # def form_valid(self, form):
    #    print(form.cleaned_data)
    #    return super().form_valid(form)


 class ContatoListView(ListView):
     template_name = 'contato/contato_list.html'
     model = Contato # This does the work for you

     #** You don't need to do this, unless you want a _specific_ queryset filterd
     # queryset = Contato.objects.all() 



 class ContatoDetailView(DetailView):
    template_name = 'contato/contato_detail.html'
    model = Contato # again, just define the model

    #** let CBV handle this logic
    # def get_object(self):
    #    id_ = self.kwargs.get("id")
    #    return get_object_or_404(Contato, id=id_)

class ContatoUpdateView(UpdateView):
    template_name = 'contato/contato_create.html'
    form_class = ContatoModelForm
    model = Contato # again, just define the model

    #** let CBV handle this logic
    # def get_object(self):
    #    id_ = self.kwargs.get("id")
    #    return get_object_or_404(Contato, id=id_)

    #** Let the ModelForm handle the validation
    #def form_valid(self, form):
    #    print(form.cleaned_data)
    #    return super().form_valid(form)


class ContatoDeleteView(DeleteView):
    template_name = 'contato/contato_delete.html'
    model = Contato # the class object you want to delete

    #** let CBV handle this logic
    # def get_object(self):
    #   id_ = self.kwargs.get("id")
    #    return get_object_or_404(Contato, id=id_)

    def get_success_url(self):
        return reverse('contato:contato-list')

【讨论】:

  • 那么在 ContatoDetailView 类中如何获取 id 呢? @guillermochamorro
  • 好的,明白了,我阅读了有关 CBV 的文档,但在我的 urls.py 中,我将 &lt;int:id> 更改为 &lt;int:pk&gt;,而不是 DetailView 正在工作,但 &lt;int:id&gt; ListView 何时可用工作和细节没有。 @guillermochamorro。
  • @PatrickAmaral 由于 ListView 检索您不使用 pk 调用它的对象的 list,它适用于 one 对象。跨度>
  • 我不明白,因为我没有用pk调用ListView,我更改了DeitailView url并且ListView停止工作。 @guillermochamorro
  • MMhh 奇怪的是,更改一个 url 会使另一个不起作用。但是当你说“停止工作”时,你到底是什么意思?是否有错误,在这种情况下是什么?
猜你喜欢
  • 2012-01-23
  • 2019-02-26
  • 1970-01-01
  • 2018-01-07
  • 2011-04-10
  • 2020-02-13
  • 2012-08-31
  • 1970-01-01
  • 2018-01-11
相关资源
最近更新 更多