Django POST URL error

Question:

I am trying to make a REST Api in Django by outputting Json. I am having problems if i make a POST request using curl in terminal. The error i get is

You called this URL via POST, but the URL doesn’t end in a slash and
you have APPEND_SLASH set. Django can’t redirect to the slash URL
while maintaining POST data. Change your form to point to
127.0.0.1:8000/add/ (note the trailing slash), or set APPEND_SLASH=False in your Django settings.

My url.py is

    from django.conf.urls.defaults import patterns, include, url
import search

# Uncomment the next two lines to enable the admin:
# from django.contrib import admin
# admin.autodiscover()

urlpatterns = patterns('',

    url(r'^query/$', 'search.views.query'),
    url(r'^add/$','search.views.add'),
)

and my views are

# Create your views here.
from django.http import HttpResponse
from django.template import Context,loader
import memcache
import json

def query(request):
    data=['a','b']

    mc=memcache.Client(['127.0.0.1:11221'],debug=0)
    mc.set("d",data);

    val=mc.get("d")

    return HttpResponse("MEMCACHE: %s<br/>ORIGINAL: %s" % (json.dumps(val),json.dumps(data)) )

def add(request):
    #s=""
    #for data in request.POST:
    #   s="%s,%s" % (s,data)
    s=request.POST['b']
    return HttpResponse("%s" % s)

I know its not giving Json but I’m having the problem mentioned above when i make POST request in terminal

curl http://127.0.0.1:8000/add/ -d b=2 >> output.html

I am new to django though.

Asked By: Zabi

||

Answers:

For URL consistency, Django has a setting called APPEND_SLASH, that always appends a slash to the end of the URL if it wasn’t sent that way to begin with. This ensures that /my/awesome/url/ is always served from that URL instead of both /my/awesome/url and /my/awesome/url/.

However, Django does this by automatically redirecting the version without the slash at the end to the one with the slash at the end. Redirects don’t carry the state of the request with them, so when that happens your POST data is dropped.

All you need to do is ensure that when you send your POST, you send it to the version with the slash at the end.

Answered By: Chris Pratt

First, make sure that you send the request to http://127.0.0.1/add/ not http://127.0.0.1/add.

Secondly, you may also want to exempt the view from csrf processing by adding the @csrf_exempt decorator – since you aren’t sending the appropriate token from cURL.

Answered By: Burhan Khalid

FOR GET ==>http://127.0.0.1:8000/create?name=wpwqekhqw/

For POST ==> http://127.0.0.1:8000/create/?name=wpwqekhqw/

You should add ‘/’ after create in POST … request

Answered By: Vageesha khandika

Another scenario can raise the exact error, not related to either csrf or APPEND_SLASH solution, below an example.

 def post(self, request, *args, **kwargs):
        data= request.data
        print(data['x'])

If ‘x’ does not exist in the payload body, the data[‘x’] will raise an error, this error in my case gave a false message like the above one.
Hopefully, this will help other developers.

Answered By: Feras

Make change in action in Html.
It’s worked in my case.

<form action="{% url 'add' %}" method="post">
    {% csrf_token %}
    ...
</form>
Answered By: shoaib21

Simply remove trailing slash from your URLs

urlpatterns = [
    path('', views.home, name= 'home'),
    path('contact/', views.contact, name= 'contact'),
    path('about/', views.about, name= 'about')
]

Change to

urlpatterns = [
    path('', views.home, name= 'home'),
    path('contact', views.contact, name= 'contact'),
    path('about', views.about, name= 'about')
]

OR

Add trailing slash to action in HTML Form

 <form method="POST" action="/contact/">
    {% csrf_token %}

It worked for me

Answered By: Chaitanya Mogal

Remove the slash on url.py

Ex:
From:

url(r'^customer/json/set_person/$', views.json_set_person, name='fog.apps.views.json.set_person'),

To:

url(r'^customer/json/set_person$', views.json_set_person, name='fog.apps.views.json.set_person'),
Answered By: CelzioBR

It can be served the urls with and without trailing slash by "/?":

in django 3.X:

from django.urls import re_path
re_path(r'^query/?$', 'search.views.query'),
re_path(r'^add/?$','search.views.add'),
Answered By: r_agha_m

In my case,I forget to add AjaxAdmin when I use simple-ui.

From:

@admin.register(xxx)
class xxxAdmin(ExportActionMixin, GAdmin):

To:

@admin.register(xxx)
class xxxAdmin(ExportActionMixin, GAdmin, AjaxAdmin):
Answered By: David Zhu