Unable to POST data with the Django REST Framework : Not Found - python

I'm trying to figure out why the Django REST Framework throws a 404 Not Found when I POST data with the code below, because when I load the browsable API with the URL it correctly displays the object list with the HTML form to POST data.
The Django project that serve the API run in a Docker container as well as the client, but in a separate Docker host.
How could I fix the issue ?
Server
Console logs
django-1 | Not Found: /api/strategy/target/
django-1 | [26/Sep/2022 14:27:05] "POST /api/strategy/target/ HTTP/1.1" 404 23
project/project/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path("api/strategy/", include("strategy.urls")),
]
strategy/urls.py
from django.urls import path, include
from rest_framework import routers
from strategy.api.views import TargetViewSet
router = routers.DefaultRouter()
router.register("target", TargetViewSet, basename="targets-list")
urlpatterns = [
path('', include(router.urls)),
]
strategy/views.py
from rest_framework import viewsets
from strategy.api.serializers import TargetSerializer
from rest_framework.decorators import permission_classes
from rest_framework.permissions import IsAdminUser
# Create new model
#permission_classes([IsAdminUser])
class TargetViewSet(viewsets.ModelViewSet):
serializer_class = TargetSerializer
queryset = Target.objects.all()
Client
res = requests.post("http://1.2.3.4:8001/api/strategy/target/",
data=data,
headers={'Authorization': 'Bearer {0}'.format(token)}
)

router.register("target", TargetViewSet, basename="targets-list")
The defination of the router is correct but I think the basename you have there is the problem. Since you have a queryset defined in your views, you can remove the basename completely. You only need to use basename if you define your own get_queryset function.
So try this and let's see if it works out for you.
router.register("target", TargetViewSet")

Related

Django Rest Framework API POST receiving status code 200 instead 201

I am new to Django and python. I have a website that already in production using docker. And the API URL is on: http://gmlews.com/api/data. When I want to test the API using postman, the GET method working fine, but for the POST method is returned response 200 OK not 201 created. Because of that, my data can't be saved in the API.
Here is my code for the API :
restapi/serializers.py:
from .models import Data,Node
from rest_framework import serializers
class DataSerializer(serializers.ModelSerializer):
class Meta:
model = Data
fields = '__all__'
class NodeSerializer(serializers.ModelSerializer):
class Meta :
model = Node
fields = '__all__'
restapi/views.py:
import json
from django.views.generic import View
from django.shortcuts import render
from rest_framework import routers, serializers, viewsets
from rest_framework.response import Response
from restapi.serializers import DataSerializer, NodeSerializer
from restapi.models import Data, Node
from django_filters.rest_framework import DjangoFilterBackend
from django.http import HttpResponse
from rest_framework.views import APIView
# Create your views here.
class DataViewSet(viewsets.ModelViewSet):
queryset = Data.objects.all()
serializer_class = DataSerializer
filter_backends = [DjangoFilterBackend]
filterset_fields = ['node_id']
class MapViewSet(viewsets.ModelViewSet):
queryset = Data.objects.filter(node_id=1).order_by('-id')[:1]
serializer_class = DataSerializer
class NodeViewSet(viewsets.ModelViewSet):
queryset = Node.objects.all()
serializer_class = NodeSerializer
urls.py:
from django.contrib import admin
from django.contrib.auth import views as auth_views
from django.urls import include, path
from restapi import views
""" for routers api root"""
from restapi.models import Data, Node
from rest_framework import routers
from restapi.views import DataViewSet, NodeViewSet, MapViewSet
router = routers.DefaultRouter()
router.register(r'data', DataViewSet, 'data')
router.register(r'node', NodeViewSet, 'node')
router.register(r'map', MapViewSet, 'map')
urlpatterns = [
path('admin/', admin.site.urls),
path(r'api/', include(router.urls)),
path(r'', include('rest_framework.urls', namespace='rest_framework')),
]
Can someone help me with this issue? I really don't have an idea why the POST method received status 200. I want it to received status 201 so my data can be saved. Thank you
Acessed your site and did a post. It returned a 201.
Follow is the evidence:
If you access you data, the item with id 15 was created by me, and the current response for that POST was a 201.

how to Create Nested router urs in rest_framework?

i have created a url using NestedSimpleRouter. And the url that i have created is that :
http://localhost:8000/api/category/1/subcategory/
And In above url 1 in the id of category .And my problem is that
i want to create the url like this
http://localhost:8000/api/category/1/subcategory/1/interest
this 1 is subcategory_id
So How can i define Nested url for this url .My urls.py is given below:
urls.py:
from django.urls import path,include
from rest_framework_nested import routers
from campaignapp import views
router = routers.DefaultRouter()
router.register('campaign',views.CampaignViewSet)
router.register('interestbundle',views.InterestBundleViewSet)
router.register('category',views.CategoryViewSet,'category')
category_router = routers.NestedSimpleRouter(router, r'category', lookup='category')
category_router.register(r'subcategory', views.SubcategoryViewSet, base_name='category-subcategory')
urlpatterns = [
path('',include(router.urls)),
path('',include(category_router.urls))
]
You can add extra actions to your viewset using action or list_route or detail_route(older version of django rest framework) decorator. This decorator is applicable all ViewSets which inherit from ViewSetMixin class.

Django define default view with IP address

I migrated my Django project to an Ubuntu distant server. I'm using mod_wsgi in order to runserver and I have some questions about default page.
I'm really new in this domain and I apologize if my question is bad or useless ..
When I want to connect to my Django application, I have to write something like that :
http://172.XX.XX.XXX/Home/login/
If I write just :
http://172.XX.XX.XXX
I get :
Page not found
Using the URLconf defined in Etat_civil.urls, Django tried these URL patterns, in this order:
^admin/
^BirthCertificate/
^Identity/
^Accueil/
^Home/
^captcha/
^Mairie/
The current URL, , didn't match any of these.
My question is :
How I can define redirected url in order to write http://172.XX.XX.XXX in my browser and go directly to http://172.XX.XX.XXX/Home/login/ for example ?
This is urls.py file from my project :
from django.conf.urls import url, include
from django.contrib import admin
from django.conf.urls.static import static
from django.conf import settings
from BirthCertificate import views
from Identity import views
from Accueil import views
from log import views
from Mairie import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^BirthCertificate/', include('BirthCertificate.urls')),
url(r'^Identity/', include('Identity.urls')),
url(r'^Accueil/', include('Accueil.urls')),
url(r'^Home/', include('log.urls')),
url(r'^captcha/', include('captcha.urls')),
url(r'^Mairie/', include('Mairie.urls')),
]
Because I just want for example, write my IP adress in order to access to my Django application and not write all the time a complete url.
If you need some files (apache2 files, ...) please tell me which one I have to post there.
Include this in views.py file of your any app:
from django.shortcuts import redirect
def some_view(request):
return redirect('/Home/login/')
Suppose the view is in log app then,
Include this in your urls.py:
from log.views import some_view
urlpatterns = [
url(r'^$', some_view,name='index'),
url(r'^admin/', admin.site.urls),
url(r'^BirthCertificate/', include('BirthCertificate.urls')),
url(r'^Identity/', include('Identity.urls')),
url(r'^Accueil/', include('Accueil.urls')),
url(r'^Home/', include('log.urls')),
url(r'^captcha/', include('captcha.urls')),
url(r'^Mairie/', include('Mairie.urls')),
]
One method is to use RedirectView by making the following changes to your urls.py:
from django.views.generic.base import RedirectView
urlpatterns = [
url(r'^$', RedirectView.as_view(url='/Home'), name='home'),
...
]
You can either do this in Django or Configure from your webserver. Django has redirects app go through https://docs.djangoproject.com/en/1.10/ref/contrib/redirects/ for more info. You just add the source and redirect urls in the redirects section of your django admin.

Django Homepage 400 when debug=False

So my app works fine in the development server when Debug=True, however, when I switch it to False, my homepage is giving me back a 400 back. I have some endpoints which return json and they work fine regardless of the debug value.
I'm using Django 1.10.2
urls.py
from django.conf.urls import url
from django.contrib import admin
from fim_table import views
urlpatterns = [
url(r'^$', views.create_home),
url(r'^data/', views.data),
...
]
views.py
from django.shortcuts import render
from django.views.decorators.csrf import csrf_protect
from lockdown.decorators import lockdown
from .models import Fim, FimDeleted
from django.http import HttpResponse
from django.db.models.functions import Lower
from django.template.context_processors import csrf
import json
#csrf_protect
def create_home(request):
return render(request, 'table.html', {'csrf': csrf})
# returns all of the data, unfiltered/response is json
#csrf_protect
def data(request):
# show distinct names only
fims = Fim.objects.annotate(name_lower=Lower('crib_name')).order_by('name_lower').distinct('name_lower')
# fims need to be not a queryset but an array of dicts to be json
dictionaries = [ idToString(name.as_dict()) for name in fims ]
mydata = {"aaData": dictionaries}
return HttpResponse(json.dumps(mydata), content_type='application/json')
settings.py
DEBUG = False
ALLOWED_HOSTS = ["*"]
update
I implemented some logging, and got:
The joined path (/DataTables/datatables.min.css) is located outside of the base path component (/Users/me/development/my_project/myapp/staticfiles).
I'm thinking this is a whitenoise issue, even though I set up my settings.py exactly like it is in their docs
Try adding hostnames in the allowed hosts section.
For Ex: ALLOWED_HOSTS = ['localhost', 'localhost_projectname', 'server_hostname']
You can find more details about how to add 404 and 500 pages in your site in the given blog post,
https://micropyramid.com/blog/handling-custom-error-pages-in-django/

Django reporting 404 error on simple view?

I'm just barely getting started with Python and Django.
I've created my modules, migrated, added my modules to the admin section, etc. Now, I need to create my first view. I've been following this guide (Yes the machine I'm on is running 1.6)
My views.py file in the app (setup) looks like this...
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
return HttpResponse("Setup Index")
My app'a urls.py looks like this...
from django.conf.urls import patterns, url
from setup import views
urlpatterns = patterns('',
url(r'^$', views.index, name='index')
)
And my root urls.py looks like this...
from django.views.generic import TemplateView
from django.views.generic.base import RedirectView
from django.conf.urls import include, patterns, url
from django.contrib import admin as djangoAdmin
from admin.controller import ReportWizard
from admin.forms import reportDetailsForm, reportDataViewsForm
from setup import views
djangoAdmin.autodiscover()
urlpatterns = patterns('',
url(r'^django-admin/', include(djangoAdmin.site.urls)),
#New User Wizard URL
url(r'^setup/', include('setup.urls')),
)
As far as I can tell I have followed the guide to the letter, but I am recieving a 404 error when navigating to myIP/setup.
There are no error messages on the 404 page. What is the issue?
For some reason your settings seem to override the default for either APPEND_SLASH or MIDDLEWARE_CLASSES.
Opening http://example.com/setup should cause a redirect to http://example.com/setup/, but somehow it doesn't for you.
Note that the latter URL is matched by your urls.py while the former is not (as should be the case).
The above should work if 'CommonMiddleWareis enabled andAPPEND_SLASHis set toTrue`.

Categories