Django Ajax jQuery URL

I have the following template file, where I am going to perform an ajax request. If I click on the show link in the template the jquery function gets executed and then I receive the following error message in the developer console of my browser:

  • TypeError at /projects/djangobook/discussions/5/show/8

  • 'NoneType' object is not callable

Traceback:

File "/Users/sebastian/Developer/Zaumdo/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response 115. response = callback(request, *callback_args, **callback_kwargs)

File "/Users/sebastian/Developer/Zaumdo/lib/python2.7/site-packages/django/views/generic/base.py" in view 68. return self.dispatch(request, *args, **kwargs)

File "/Users/sebastian/Developer/Zaumdo/lib/python2.7/site-packages/braces/views.py" in dispatch 107. request, *args, **kwargs)

File "/Users/sebastian/Developer/Zaumdo/Zaumdo/core/mixins.py" in dispatch 49. return super(GroupAwareMixin, self).dispatch(request, *args, **kwargs)

File "/Users/sebastian/Developer/Zaumdo/lib/python2.7/site-packages/django/views/generic/base.py" in dispatch 86. return handler(request, *args, **kwargs)

Exception Type: TypeError at /projects/djangobook/discussions/5/show/8

Exception Value: 'NoneType' object is not callable

Request information: GET: No GET data

POST: name = u'sebastian'

FILES: No FILES data

COOKIES: csrftoken = 'fWD0OojhrpTLhuxtxb2NF96rVSnKGpWy' sessionid = 'fccuv36b538pqnulqyhbdsq7ihyrvjo5'

template.html

{% for post in object_list %}
    {{ post.creator }}
    {{ post.created }}
    {{ post.body }}
    <a href="{% groupurl post_answer group discussion_id=discussion.id pk=post.id %}">Answer</a>
    <a class="show_answers" href="{% groupurl post_show_answers group discussion_id=discussion.id post_id=post.id %}">Show</a>
{% endfor %}

<script type="text/javascript">
    $(".show_answers").click(function(e) {
        e.preventDefault();
        var self = $(this);
        ajax_req = $.ajax({
            url: self.attr("href"),
            type: "POST",
            data: {name: "sebastian"},
            success: function(ctx) {console.log(ctx);}
        });
    });
</script>

urls.py

from django.conf.urls import patterns, url

from discussions.views import DiscussionListView, DiscussionCreateView, DiscussionUpdateView,
DiscussionDeleteView, PostListView, PostCreateView, PostAnswerView

urlpatterns = patterns\
(
    'discussions.views',
    url(r'^$', DiscussionListView.as_view(), name='discussion_list'),
    url(r'^create/$', DiscussionCreateView.as_view(), name='discussion_create'),
    url(r'^update/(?P<pk>\d+)$', DiscussionUpdateView.as_view(), name='discussion_update'),
    url(r'^delete/(?P<pk>\d+)$', DiscussionDeleteView.as_view(), name='discussion_delete'),
    url(r'^(?P<discussion_id>\d+)/$', PostListView.as_view(), name='discussion'),
    url(r'^(?P<pk>\d+)/create/$', PostCreateView.as_view(), name='post_create'),
    url(r'^(?P<discussion_id>\d+)/answer/(?P<pk>\d+)', PostAnswerView.as_view(), name='post_answer'),
    url(r'^(?P<discussion_id>\d+)/show/(?P<post_id>\d+)', PostListView.as_view(), name='post_show_answers'),
)

In this view I would like to send an HttpResponse.

views.py

class PostListView(LoginRequiredMixin, GroupAwareMixin, ListView):
    model = Post
    template_name = 'discussions/discussion.html'

    discussion = None
    post = None
    posts = None

    def get_queryset(self):
        # Get the discussions from the pk in the url
        self.discussion = get_object_or_404(Discussion, pk=self.kwargs['discussion_id'])

        # return HttpResponse(json.dumps("success"), mimetype="application/json")

        # Fetch all the root posts (depth=1) in the discussion
        self.posts = self.discussion.posts.filter(depth=depth)
        return self.posts

    def get_context_data(self, **kwargs):
        context = super(PostListView, self).get_context_data(**kwargs)
        context['discussion'] = self.discussion
        return context

Django to send a request using ajax is necessary to generate a token as explained in the documentation csrf_token.

I develop my applications in this token as follows.

In layout.html

<html>
    <head>...</head>
    <body>
       <!--the end of the body tag -->
       {% csrf_token %}

       <script type="text/javascript">
           $tagToken = $("{% csrf_token %}");
           var CSRF_TOKEN = $tagToken.find("input[name='csrfmiddlewaretoken']").val();
       </script>
    </body>
</html>

Now in file js.

$(".show_answers").click(function(e) {
    e.preventDefault();
    var self = $(this);
    ajax_req = $.ajax({
        url: self.attr("href"),
        type: "POST",
        data: {name: "sebastian"},
        beforeSend: function(xhr, settings) {
            if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
                xhr.setRequestHeader("X-CSRFToken", CSRF_TOKEN);
            }
        },
        success: function(ctx) {console.log(ctx);}
    });
});

That would be all for you to accept the request django.

Exception throws on calling handler(request, *args, **kwargs) in dispatch function because your view didnt have post method:

# django.views.generic.base.py:
def dispatch(self, request, *args, **kwargs):
    # Try to dispatch to the right method; if a method doesn't exist,
    # defer to the error handler. Also defer to the error handler if the
    # request method isn't on the approved list.
    if request.method.lower() in self.http_method_names:
        handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
    else:
        handler = self.http_method_not_allowed
    return handler(request, *args, **kwargs)

Your ajax post url is same as page url:

    ajax_req = $.ajax({
        url: self.attr("href"),
        ...

So, you should add post method to your view class.