Django使用通用视图,错误HTTP 405

时间:2018-09-23 22:12:55

标签: django http-status-code-405

我正在尝试将django通用视图用于CRUD,但是按照官方Django https://docs.djangoproject.com/en/2.1/ref/class-based-views/generic-editing/的指南,DeleteView导致错误405,我不知道我的错误在哪里,所以这就是我的代码:

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 %}

2 个答案:

答案 0 :(得分:0)

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

基本上将<form>的打开标记更改为:

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

,然后通过idcontext传递到视图,如下所示:

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)

作为一项附加建议,我将考虑使您的路线更具REST风格。有关信息,请参见以下要点:https://gist.github.com/alexpchin/09939db6f81d654af06b。不过要注意的是HTML5表单不支持删除(或放置)请求。要使用表单提出删除请求,您必须在使用javascript提交后手动提交请求。

答案 1 :(得分:0)

简化代码:

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')