POST JSON request data dropped/disappear when sending to djangorestframework - python

I get stuck on making a simple RESTful test using django-rest-framework. I am new beginner to this. Please help. Thanks in advance!
version:
django >= 1.9
djangorestframework 3.3.3
python 3.4.3
POST request from terminal
curl -H "Content-Type: application/json" -X POST -d '{"title":"xyz","desc":"xyz"}' http://localhost:3000/api/test/
django's settings.py
INSTALLED_APP = {
'app',
'rest_framework',
#....skip to keep it short
}
# did not set anything
<!-- language-all: lang-python -->
REST_FRAMEWORK = {
}
# models.py
class Test(object):
def __init__(self, title, desc):
self.title = title
self.desc = desc
serializers.py
from rest_framework import serializers
class TestSerializer(serializers.Serializer):
title = serializers.CharField()
desc = serializers.CharField(max_length=200)
class Meta:
model = Test
fields = ('title', 'desc')
views.py
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
#csrf_exempt
class TestView(APIView):
def get(self, request, format=None):
# 1. we use NoSQL, is the following line still work?
# testItems = Test.objects.all()
serializer = SnippetSerializer(testItems, many=True)
return Response(serializer.data)
def post(self, request, format=None):
# 2. Unable to get any json string in request object or request.data at all!
# 3. The entire json seems disappear and get dropped
serializer = TestSerializer(data=request.data)
if serializer.is_valid():
# 4. can save() be overrided and do custom implementation? How?
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
urls.py
from django.conf.urls import patterns, url
urlpatterns = patterns(
'app',
url(r'^api/business/$', app.views.TestView.as_view()),
)
My Questions:
we use NoSQL, is the following line still work?
testItems = Test.objects.all()
empty request.data in POST JSON request.
Unable to get any json string in request object
or request.data at all! The entire json seems disappear and get
dropped. Tried to use Fiddler/Postman capture and ensure JSON did sent out
Can save() be overrided and do custom implementation? How?

I don't know about NOSQL but you can test it on shell. I'm guessing probably it works.
About request.data error; request.data is only used for file upload with django rest framework. When you post a json, it's in the body of the request. What you should do is something like this in your view:
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
import json
#csrf_exempt
class TestView(APIView):
# your get request here.
def post(self, request, format=None):
body_unicode = request.body.decode('utf-8')
data = json.loads(body_unicode)
# Now, your json content is stores in data as a dictionary.
serializer = TestSerializer(data=request.data)
if serializer.is_valid():
# 4. can save() be overrided and do custom implementation? How?
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
FYI,I use serializers for just creating json, I don't use it to create object. Therefore, I'm not sure if this version %100 works or not. But I'm pretty sure that 2 line I've added turns JSON to dictionary. If serializer accepts dictionary as a data, it'll work.

Related

AssertionError: Cannot apply DjangoModelPermissionsOrAnonReadOnly

I have a problem with (I think) permissions. When I try to send post request via postman, I get following error:
AssertionError: Cannot apply DjangoModelPermissionsOrAnonReadOnly on a view that does not set .queryset or have a .get_queryset() method.
[29/Nov/2021 20:21:21] "POST /api/blog/category HTTP/1.1" 500 101581
Here are my views.py and category class. Also, I noticed that for some reason in def post(self, request, format=None) request is not being called ("request" is not accessed Pylance). I think the problem is somewhere here, but can't figure it out. Thank you in advance.
class BlogPostCategoryView(APIView):
serializer_class = BlogPostSerializer
permissions_classes = (permissions.AllowAny, )
def post(self, request, format=None):
data = self.request.data
category = data['category']
queryset = BlogPost.objects.order_by('-date_created').filter(category__iexact=category)
serializer = BlogPostSerializer(queryset, many=True)
return Response(serializer.data)
In settings.py you can add:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.BasicAuthentication',
]
}
Then in postman go to the Authorization tab and for type select Basic Auth.
You can then enter your username and password. You should be able to make Post requests after this.

Suddenly my api_view is not defined. Why?

I am making a webpage using React frontend and Django backend. I have trouble running my backend because things supposedly aren't defined. E.g. I get this message when trying to run
python manage.py makemigrations
getting error,
name 'api_view' is not defined
What can I do to fix it?
from django.http import HttpResponse
from .serializers import UserSerializer
def homePageView(request):
return HttpResponse('Hello, World!')
#
#api_view(['POST'])
def createUserView(request):
# Create a new user
if request.method == 'POST':
# Create serializer with data from new user object
serializer = UserSerializer(data=request.data) #datafeltet inneholder json fra frontend, se eks. nederst
if serializer.is_valid():
# Save user
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
#return HttpResponse('User')
You need to import from api_view decorator as,
from rest_framework.decorators import api_view
Check that you are using correct virtual enviornment.
And make sure that rest_framework is installed or not using pip freeze

i'm not able to understand why i have to restart the server to see the changes made by a Put request (django rest framework)

The put request is working, but if i want to see the post updated i have to restart the server.
This is the view function:
from rest_framework import status
from rest_framework.response import Response
from rest_framework.decorators import api_view
from blog.models import Post
from .serializers import PostSerializer
from django.contrib.auth.models import User
#api_view(['PUT'])
def api_update_post_view(request, Slug):
try:
blog_post = Post.objects.get(slug=Slug)
except Post.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
serializer = PostSerializer(blog_post, data=request.data, partial=True)
data = {}
if serializer.is_valid():
serializer.save()
data['succes'] = 'update successful'
return Response(data=data)
return Response(serializer.errors, status.HTTP_400_BAD_REQUEST)
I didn't see any special features in your PUT method. So, I suggest you to use ModelViewSet instead of creating a basic PUT method yourself. ModelViewSet will generate basic CRUD operations for you automatically.
Here is the official docs. It should be no problem after you use the ModelViewSet.

DRF Post to ViewSet without writing into Model

I've always written data into database when posting via Django Rest Framework endpoints. This time I would like to process received data and send it somewhere else without writing into DB. I switched from ModelViewSet to ViewSet, I can issue GET request OK but receiving Bad Request 400 when I curl or POST via DRF URL. Here's a working minimal code (removed need for authentication etc):
urls.py
from django.urls import path, include
from .views import ContactView
from rest_framework import routers
router = routers.DefaultRouter()
router.register('message', ContactView, basename='message')
urlpatterns = [
path('', include(router.urls)),
]
serializers.py
from rest_framework import serializers
class ContactSerializer(serializers.Serializer):
text = serializers.CharField(max_length=250)
views.py
from rest_framework.response import Response
from .serializers import ContactSerializer
from rest_framework import viewsets
class ContactView(viewsets.ViewSet):
def list(self, request):
return Response('Got it')
def create(self, request):
serializer = ContactSerializer(data=request.data)
if serializer.is_valid():
return Response(serializer.data)
else:
return Response('Invalid')
Would greatly appreciate your suggestions.
You can use GenericAPIView for get or post request and do some logic in validate method, for example do something with signals or edit something. Also u can use #detailt_route or #list_route for any ModelViewSet for write special url for instance, example for edit extra data.
how i did rarely:
in urls.py
urlpatterns = [
url('v1/message', ContactAPIView.as_view(), name='message'),
]
in view.py
class ContactAPIView(GenericAPIView):
serializer_class = ContactSerializer
permission_classes = ()
def post(self, request, *args, **kwargs):
serializer_class = self.get_serializer_class()
serializer = serializer_class(data=request.data, context={'request': request})
serializer.is_valid(raise_exception=True)
data = {"status": True}
return Response(data)
in serializers.py
class ContactSerializer(serializers.Serializer):
text = serializers.TextField()
def validate(self, attrs):
write some logic
you are getting this error because you are using Viewsets which uses DefaultRouter to register routers for you. What it does is that it creates 2 urls for your viewset
message
message/id
so in your current case; i.e. viewset you need to send some dummy number in your url to access this post function (which is not a good approach).
So, you should use any class which parent doesn't include ViewSetMixin (which gives functionality of Router Registration) like in your case inherit your view from these classes
ListModelMixin
CreateModelMixin
GenericAPIView

Django rest_framework request post data to remote server using class views and modelviewset

I am new to Django and rest_frameworks. A Django app that is using REST_Framework which looks like below
The goal is that when a a POST is called, the form data/json is sent to remote server url, using "request.post". Currently the code gives no errors, however the data is not posted to the remote server url.
My sample code for the class view is below:
class SnippetViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows containers to be viewed or edited.
"""
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
#detail_route(methods=['post'])
def snippet_detail(self, request):
Snippet = self.get_object()
serializer = SnippetSerializer(data=request.data)
if serializer.is_valid():
headers= {"Content-type":"application/json", "encoding":"utf-8"}
url = "http://198.0.10.1:5000/create?name=rstudio"
r = requests.post(url, data=json.dumps(serializer), headers =headers)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors,
status=status.HTTP_400_BAD_REQUEST)
Add .data to the serializer in json.dumps.
r = requests.post(url, data=json.dumps(serializer.data), headers=headers)

Categories