Michael Michael - 1 month ago 5x
Ajax Question

I can use ajax from /edit but not from /detail

Django 1.10.

From DetailView I want to update the model object via ajax. Well, the model object is updated. But the ajax success function can't get data from the post method. I occur in failure function.

In other words, in Django in UpdateView I can stop at a breakpoint in form_valid, control that it returns an HttpResponse with code 200. And later if I refresh page with detail information, I can see that the model object has changed.

But in In Chrome dev tools while debugging js I occur in fail function. And jqXHR.status=0, textStatus = "error", errorThrown="".

I have prepared a simulation of my real situation:

There is a difference: this UpdateView renders the general_detail.html. In real life it should render partial_detail.html. Well, it is ajax, we don't need to reload the whole page.

So, this simulation renders the whole page. What does it mean? It means that:

1) If I'm in http://localhost:8000/1/detail, pressing AjaxEdit link leads me to the failure. Not working. In Chrome developers tools I occur in failure function.

2) I return to http://localhost:8000/1/detail, press Edit. I occur in http://localhost:8000/1/edit. This is ordinary editing without ajax. But the view is organized so that to render a response without redirect. So, I save the model and stay in http://localhost:8000/1/edit. And I can see the whole details as if I were looking at the result of a proper DetailView. There are two control links: Edit and AjaxEdit. And now AjaxEdit starts working.

In other words, at http://localhost:8000/1/edit ajax works, at http://localhost:8000/1/detail it doesn't.

I've just started learning ajax. I can't cope with this. I would say that a redirect may influence. But there is no redirect.

Via ajax I address to the get method of the view and get a proper data. What is the difference compared to post.

Could you comment on it and help me break through.


class GeneralUpdate(UpdateView):
model = General
fields = ['char']

def form_valid(self, form):
self.object = form.save()
return render(self.request, 'general/general_detail.html', {"object": self.object})


class General(models.Model):
char = models.CharField(max_length=100)

def get_absolute_url(self):
return reverse("detail", kwargs={"pk": self.id})


urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^create$', GeneralCreate.as_view(), name="create"),
url(r'^(?P<pk>\d+)/detail$', GeneralDetailView.as_view(), name="detail"),
url(r'^(?P<pk>\d+)/edit$', GeneralUpdate.as_view(), name="edit"),


<form id="form" action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input id="submit" type="submit" value="Save" />


<p id="char">{{ object.char }}</p>

<a href="{% url "edit" object.id %}">Edit</a>
<a id="ajax_edit" href="javascript:void(0)">AjaxEdit</a>

<script src="https://code.jquery.com/jquery-3.1.0.min.js" integrity="sha256-cCueBR6CsyA4/9szpPfrX3s49M9vUU5BgtiJj06wt/s=" crossorigin="anonymous"></script>
$( document ).ready(function() {
var ajax_edit = $("#ajax_edit");
var char = $("#char");

function show_get(data){
var submit_link = $("#submit");

function show_post(data){

function failure(jqXHR, textStatus, errorThrown){

function post(){
method: "post",
data: $("form").serialize(),
url: 'http://localhost:8000/2/edit',
success: show_post,
error: failure,

function get(){
method: "get",
url: 'http://localhost:8000/2/edit',
success: show_get,




If I understand it correctly...

  1. You click AjaxEdit - it fetches response from UpdateView and loads it directly into your /detail page. You technically still on detail page now.
  2. You check your form in chrome dev and see that form action attribute points to nothing.
  3. You click Save and your ajax request updates data as planned.
  4. Then default submit happens and your POST request goes to /detail url since technically you are still on details page.
  5. Django's DetailView forbids POST requests and kick it with 405 HTTP status (Method not Allowed), check it in chrome inspector.

So that's the main reason.

As a fix you can disable default submit action by adding


before submit_link.click(post);