Django REST API: How to respond to POST request? - django

I want send POST request with axios(VueJS) and when Django server got a POST request then I want to get back that request message.
I tried make functions when got an POST request in Django server and then return JsonResponse({"response": "got post request"), safe=False)
JS function
sendMessage() {
axios({
method: "POST",
url: url,
data: this.message
})
.then(response => {
this.receive = response;
})
.catch(response => {
alert('Failed to POST.' + response);
})
}
}
views.py
from chat.serializer import chatSerializer
from chat.models import *
from rest_framework.routers import DefaultRouter
from rest_framework import viewsets
from django.http import JsonResponse
from django.views.generic import View
# Create your views here.
class get_post(View):
def post(self, request):
if request.method == 'POST':
JsonResponse({"response": 'got post request'}, safe=False)
but error says like that in django
Internal Server Error: /api/chat/
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/django/core/handlers/exception.py", line
47, in inner
response = get_response(request)
File "/usr/lib/python3/dist-packages/django/core/handlers/base.py", line 188,
in _get_response
self.check_response(response, callback)
File "/usr/lib/python3/dist-packages/django/core/handlers/base.py", line 309,
in check_response
raise ValueError(
ValueError: The view chat.views.views.get_post didn't return an HttpResponse object. It returned None instead.
[26/Oct/2022 17:06:51] "POST /api/chat/ HTTP/1.1" 500 60946
I think POST request is working properly, but Django code is something wrong.
Therefore, my question is..
How to fix and solve this error?
When I call axios in JS, inside '.then' we got a response so which data is come to this variable? Should I return this data like Response() or JsonResponse() method?

just add a return in the view ... like this:
class get_post(View):
def post(self, request):
if request.method == 'POST':
return JsonResponse({"response": 'got post request'}, safe=False)
because the error complains that the post function must return anything.
for the second question ya you need to return JsonResponse because you are dealing with APIs.

Related

Getting 400 Bad Request from Open AI API using Python Flask

I want to get response using Flask from OpenAI API. Whether I am getting Status 400 Bad Request from Browser through http://127.0.0.1:5000/chat
Bad Request
The browser (or proxy) sent a request that this server could not understand.
Also I am checking this from Postman
from flask import Flask, request, render_template
import requests
app = Flask(__name__)
#app.route('/')
def index():
return 'Welcome to ChatGPT app!'
#app.route('/chat', methods=['GET', 'POST'])
def chat():
user_input = request.form['text']
# Use OpenAI's API to generate a response from ChatGPT
response = generate_response_from_chatgpt(user_input)
return response
def generate_response_from_chatgpt(user_input):
api_key = "YOUR_API_KEY"
url = "https://api.openai.com/v1/engines/davinci/completions"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {api_key}"
}
data = {
"prompt": user_input,
"engine": "davinci"
}
response = requests.post(url, headers=headers, json=data)
return response.json()["choices"][0]["text"]
if __name__ == '__main__':
app.run()
It would be best if you check the openai documentation to make sure you are using the correct endpoint and data format in your request.
Also, you should check your API key, if it is correct and if you have reached the limit of requests.
Also, it's worth noting that the code you provided is missing the import statement for Flask. You will need to add the following line at the top of your file:
from flask import Flask, request
Also, I see that you're using request.form['text'] but you should check if the request is a GET or POST request.
if request.method == 'POST':
user_input = request.form['text']
else:
user_input = request.args.get('text')
This is to avoid a KeyError being raised when the request is a GET request.

Unable to perform conditional redirect from a class based view Django

I am trying to redirect a user who has already registered to a different view. here is the code for the views.py
However when qs.exists() = true I get an error
'The view Lpage.views.homeview didn't return an HttpResponse object. It returned None instead.'
I am a beginner have read the documentation but unable to find where i am going worng.
Thanks
from django.shortcuts import render, redirect
from django.views import View
from Lpage.forms import SubscriberEntryForm
from Lpage.models import Subscriber
class homeview(View):
def get(self,request):
msg = request.session.get('msg', False)
if(msg):
del(request.session['msg'])
return render(request,'Lpage/index.html')
def post(self, request):
form = SubscriberEntryForm(request.POST or None)
if form.is_valid():
obj = form.save(commit=False)
qs = Subscriber.objects.filter(email__iexact=obj.email)
if qs.exists():
return redirect('messageview')
else:
obj.save()
request.session['msg'] = "msg"
return redirect(request.path)
def messageview(request):
return render(request,'Lpage/messages.html',{})
Here is the error message
ValueError at /
The view Lpage.views.homeview didn't return an HttpResponse object. It returned None instead.
Request Method: POST
Request URL: http://localhost:8000/
Django Version: 3.2.7
Exception Type: ValueError
Exception Value:
The view Lpage.views.homeview didn't return an HttpResponse object. It returned None instead.
Exception Location: C:\Users\Ganesamurthi\anaconda3\lib\site-packages\django\core\handlers\base.py, line 309, in check_response
Python Executable: C:\Users\Ganesamurthi\anaconda3\python.exe
Python Version: 3.8.5
Python Path:
['D:\dreamdoors\dd',
'C:\Users\Ganesamurthi\anaconda3\python38.zip',
'C:\Users\Ganesamurthi\anaconda3\DLLs',
'C:\Users\Ganesamurthi\anaconda3\lib',
'C:\Users\Ganesamurthi\anaconda3',
'C:\Users\Ganesamurthi\anaconda3\lib\site-packages',
'C:\Users\Ganesamurthi\anaconda3\lib\site-packages\win32',
'C:\Users\Ganesamurthi\anaconda3\lib\site-packages\win32\lib',
'C:\Users\Ganesamurthi\anaconda3\lib\site-packages\Pythonwin']
Server time: Wed, 29 Sep 2021 05:23:43 +0000
Traceback Switch to copy-and-paste view
C:\Users\Ganesamurthi\anaconda3\lib\site-packages\django\core\handlers\exception.py, line 47, in inner
response = get_response(request) …
▶ Local vars
C:\Users\Ganesamurthi\anaconda3\lib\site-packages\django\core\handlers\base.py, line 188, in _get_response
self.check_response(response, callback) …
▶ Local vars
C:\Users\Ganesamurthi\anaconda3\lib\site-packages\django\core\handlers\base.py, line 309, in check_response
raise ValueError( …
▶ Local vars
redirect expects you to pass a URL but you gave it messageview, which is a view class in fact.
So you need to give redirect to the URL of messageview.

TypeError: %d format: a number is required, not Dash

I am creating a flask-Dash app with token authentication. if the token authenticated will then I want to pass the dash.Dash() into flask app, other wise want to return a dummy dash layout. But I when I hit the route 'dashboard' getting following error. Please help me to resolve this.
Error : TypeError: %d format: a number is required, not Dash
__init.py
"""
Initialize app
"""
from flask import Flask, make_response, request, redirect, jsonify, url_for, session
import jwt
import urllib.parse
from functools import wraps
from datetime import timedelta
import os
print("__init__.py location", os.getcwd())
path = os.path.join("application", "dash_application")
#os.chdir(path)
print("directory after init", os.getcwd())
def create_app():
"""
construct the flask core application
:return: Complete app
"""
app = Flask(__name__)
app.config.from_object('config.Config')
"""
auth_request decorator is validating the token, if token is genuine then it returning to next method else
sending invalid token response to use
"""
def auth_request(f):
#wraps(f)
def wrapper(*args, **kwargs):
authorization = request.args.get('access_token') or request.headers.get('authorization')
if not authorization:
return make_response(jsonify({
"message": "Invalid request",
"token": "null",
"status": False,
"error": {
"message": "Invalid token or token missing"
}
}), 400)
try:
if request.method == "POST":
authorization = authorization[7:] # Removed first Bearer OR bearer from token
data = jwt.decode(authorization, app.config.get('SECRET_KEY'), audience=app.config.get('AUDIENCE'))
return f(data, *args, **kwargs)
authorization = urllib.parse.unquote(authorization) # Removed first Bearer OR bearer from token
data = jwt.decode(authorization, app.config.get('SECRET_KEY'), audience=app.config.get('AUDIENCE'))
return f(data, *args, **kwargs)
except Exception as e:
print(e)
return make_response(jsonify({
"message": "Invalid request",
"token": "null",
"status": False,
"error": {
"message": "Invalid token or token missing"
}
}), 400)
return wrapper
#app.route('/', methods=['GET'])
def index():
return make_response(jsonify({
"message": "Success",
"status": True,
"error": {}
}), 200)
#app.route('/authenticate', methods=['POST'])
#auth_request
def authenticate(data):
return make_response(jsonify({
"message": "successfully authenticated!",
"status": True,
"error": {}
}), 200)
#app.route('/twc-admin-panel-integration', methods=['GET'])
#auth_request
def twc_admin_panel_integration(data):
if int(data['corporateId']) > 0:
session['isAuthenticated'] = 'yes'
session['corporateId'] = 9 # data.get('corporateId')
return redirect('/dashboard/')
return make_response(jsonify({
"message": "required property is missing in token",
"status": False,
"error": {
"message": "invalid token"
}
}), 400)
#app.route('/dashboard/')
def mypage():
app = Flask(__name__)
app.config.from_object('config.Config')
# session.permanent = True
# app.permanent_session_lifetime = timedelta(minutes=app.config.get('SESSION_EXPIRY_TIME'))
# app.secret_key = app.config.get('SESSION_SECRET')
with app.app_context():
print("reached at line 109")
from application.dash_application.dashapp import add_dash
dashapp = add_dash(app, 179) # add_dash returning the dash.Dash instance
#
# if session.get('isAuthenticated') is not None:
# if 'yes' in session['isAuthenticated']:
return app, dashapp
# return redirect(app.config.get('TWC_ADMIN_URL'))
# return redirect(app.config.get('TWC_ADMIN_URL'))
with app.app_context():
from application.dash_application.dashapp import add_dash
dashapp = add_dash(app, 179)
return app, dashapp
And running this app file using WSGI DispatcherMiddleware
app.py
"""
Application entry point
"""
from application import create_app
from flask_cors import CORS
from werkzeug.middleware.dispatcher import DispatcherMiddleware
from werkzeug.serving import run_simple
def main():
flask, dash = create_app()
CORS(flask, resources={r"/*": {"origins": "*"}})
if dash:
app = DispatcherMiddleware(flask, {
'dashboard': dash.server
})
run_simple(hostname="127.0.0.1", port=8080, application=app, use_reloader=True, use_debugger=True)
if __name__=="__main__":
main()
Full error traceback is :
[2020-06-05 21:54:43,860] ERROR in app: Exception on /dashboard/ [GET]
Traceback (most recent call last):
File "D:\TWC\DashApp\crazy_corner\lib\site-packages\werkzeug\wrappers\base_response.py", line 298, in status_code
self._status = "%d %s" % (code, HTTP_STATUS_CODES[code].upper())
KeyError: <dash.dash.Dash object at 0x0000020514B01390>
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "D:\TWC\DashApp\crazy_corner\lib\site-packages\flask\app.py", line 2446, in wsgi_app
response = self.full_dispatch_request()
File "D:\TWC\DashApp\crazy_corner\lib\site-packages\flask\app.py", line 1952, in full_dispatch_request
return self.finalize_request(rv)
File "D:\TWC\DashApp\crazy_corner\lib\site-packages\flask\app.py", line 1967, in finalize_request
response = self.make_response(rv)
File "D:\TWC\DashApp\crazy_corner\lib\site-packages\flask\app.py", line 2138, in make_response
rv.status_code = status
File "D:\TWC\DashApp\crazy_corner\lib\site-packages\werkzeug\wrappers\base_response.py", line 300, in status_code
self._status = "%d UNKNOWN" % code
TypeError: %d format: a number is required, not Dash
I don't quite understand what you try to do, but in this view function mypage:
def create_app():
# ...
#app.route('/dashboard/')
def mypage():
# ...
with app.app_context():
# ...
return app, dashapp
# ...
When you return a two elements tuple, Flask will assume it's (body, status_code), and the status_code must be a number. But in your case, the second element of the tuple is a Dash object (dashapp), which causes the error. Besides, the Flask application instance (app) you returned as the first element of the tuple is not a valid response body for a view function.

Django Rest Framework: Pickle Response

What I'm trying to do is build a custom version of cache_page where I have more control over the cache key, but I'm getting stuck with even the basic caching of my response:
from django.core.cache import cache
from rest_framework import viewsets
from rest_framework.response import Response
from app import models
class BaseViewSet(viewsets.GenericViewSet):
queryset = models.Items.objects.all()
def get_queryset(self):
return models.Items.objects.all()
def list(self, request, **kwargs):
response = Response({})
cache.set('test', response, 10)
return response
Where the relevant parts of my settings.py are setup as:
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
],
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.NamespaceVersioning'
}
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": f"redis://127.0.0.1:6729/1",
},
}
When I try to call the endpoint I get:
django.template.response.ContentNotRenderedError: The response content must be rendered before it can be pickled.
Then if I change the line to:
cache.set('test', response.render(), 10)
I get:
AssertionError: .accepted_renderer not set on Response
(If I set the renderer it complains about the accepted media, then the context and finally fails with TypeError: 'bytes' object is not callable)
Despite the fact that the API call itself works fine without the caching.
cache_page actually works fine, so I know it's possible to cache the response, but I can't figure out what I'm missing.
I solved this issue by having the view return a django.http.JsonResponse rather than a rest_framework.response.Response object. The problem is that the rest_framework Response is mediatype agnostic, and as far as I can tell relies on having the renderer and accepted media values set further down the call chain of the view, after it has left your handler. Since JsonResponse only deals with json, it doesn't have to go through this "content negotiation".
cache_page
work because of this:
if hasattr(response, 'render') and callable(response.render):
response.add_post_render_callback(lambda r: self.cache.set(cache_key, r, timeout))
else:
self.cache.set(cache_key, response, timeout)

custom exception handler for DRF response and Django response

I'd like to define a custom exception class and raise it.
Django rest framework has a hook where I can define custom exception handler,
(http://www.django-rest-framework.org/api-guide/exceptions/#custom-exception-handling)
Django also provides a way to do it via middleware.
Question: If I want to handle exceptions in drf views and regular django views, would it be sufficient to handle them in django middleware?
Or do I need separate handler for DRF views?
In other words, does DRF request/response goes through django middleware as well or not?
Create a script called exception_middleware.py anywhere in the project directory (preferably in the main app directory) and add the following:
import logging
from django.shortcuts import render
from django.conf import settings
logger = logging.getLogger("StackDriverHandler")
class ExceptionMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
if settings.DEBUG:
host = "http"
else:
# TODO: set for https
host = "http"
if response.status_code == 500:
return render(request, "error_templates/500.html")
if response.status_code == 404:
return render(request, "error_templates/404.html")
if response.status_code == 403:
return render(request, "error_templates/403.html")
return response
def process_exception(self, request, exception):
try:
logger.info(request, extra=exception)
except Exception as e:
logger.error(exception)
return None
def process_exception(self, request, exception):
try:
logger.info(request, extra=exception)
except Exception as e:
logger.error(exception)
return None
Add the path to this class in the MIDDLEWARE section in the settings.py file of your Django project (at the last).
That's it. This middleware will get executed during each of your requests and will check if you are in DEBUG and if there is an exception, this middleware will then create a message for you :) .