0👍
The problem was not in the code, it’s weird that I had only to re-run Django server and the code will be executed as expected, so B.views.py
will be:
from rest_framework import views
from rest_framework.response import Response
from A.views import A
class B(views.APIView):
def post(self, request, *args, **kwargs):
http_response = A.as_view()(request._request)
return Response(http_response.data)
UPDATE
it seems that HttpRequest
AKA request._request
can’t be used multiple times after it has been read by Django Rest Framework View
parser class that will lead to call read
method which will change the _request
object’s property _read_started
to be True
, and after that if you tried to use request.data
or request._request
will raise the exception that shown above because the request.body
is not accessible anymore due it counts on the value of _read_started
property, also not to mention that the value of HttpRequest
has already been converted into stream
object and stored in the memory.
SOLUTION
There are multiple suggestions I found:
1- use Middleware
to store the request.body
to use it later in case of need.
2- use a custom parser class that store raw data as property in the request
object before converting it into stream
object.
Both of them I found is a little bit complicated, so I changed the way of calling another APIView
from certain DRF View
, as shown:
from rest_framework import views, status
from rest_framework.response import Response
from A.views import A
from C.views import C
class B(views.APIView):
def post(self, request, *args, **kwargs):
# Initialize a new instance of class view 'A'
a_view = A()
# Calling HTTP 'POST' method with DRF request object.
a_http_response = a_view.post(request)
if a_http_response.status_code == status.status.HTTP_200_OK:
# Initialize a new instance of class view 'C'
c_view = C()
# Another calling HTTP 'POST' method with DRF request object.
c_http_response = c_view.post(request)
return(c_http_response.data)
else:
return Response(a_http_response.data)
1👍
I think isn’t the best practice in Django or DRF to call a view from another. If you want to access the business logic from View A by View B, I recommend you put your business logic in a function outside, in a way you can call that function on both Views A and B.
Said that, you can call APIView A from by APIView B by invoking the HTTP method post from the DRF APIView, such as A().post(request)
.
from rest_framework import views
from rest_framework.response import Response
class A(views.APIView):
def post(self, request, *args, **kwargs):
return Response({"message": "class A"})
class B(views.APIView):
def post(self, request, *args, **kwargs):
http_response = A().post(request)
return Response({"message": http_response.data})
0👍
You can use the requests
library to send a post
to your endpoint:
A.views.py
class A(views.APIView):
def post(self, request, *args, **kwargs):
return Response({"message": "class A"})
B.views.py
import requests
class B(views.APIView):
def get(self, request, *args, **kwargs):
r = requests.post("http://localhost:8000/api/a")
r_data = r.json()
message = r_data['message']
data = {
'status_code': r.status_code,
'headers': r.headers,
'message_from_a': message
}
return Response(data)
Obs: Override get
on B
so you can see the message on browsable API.
- [Answered ]-Django three way join using Foreign Keys
- [Answered ]-Django Static Files Not Loading in Deployment
- [Answered ]-Unable to import view in Django project
- [Answered ]-'from __future__ import unicode_literals' in Django Migrations