I am trying to make the custom response format for that i have done below mentioned code
middleware
from django.utils.deprecation import MiddlewareMixin
from rest_framework.response import Response
from rest_framework.exceptions import APIException
class CustomResponseMiddleware(MiddlewareMixin):
def process_response(self, request, response):
from adminPanel.serializers import MyCustomException
if not isinstance(response, Response):
return response
response.render()
if 'data' in response.data:
return response
response_data = {
'status': response.status_code,
'message': 'Success',
'error': False,
'data': response.data,
'error_message': None,
}
if isinstance(response, MyCustomException):
error_message = response.detail.get('error_message', None)
response_data = {
'status': response.status_code,
'message': 'Error',
'error': True,
'data': None,
'error_message': error_message,
}
return Response(response_data, status=response.status_code)
in setting.py
'adminPanel.middleware.custom_response.CustomResponseMiddleware',
serializers.py
class LoginSerializer(serializers.Serializer):
username_or_email = serializers.CharField()
password = serializers.CharField(write_only=True)
access_token = serializers.CharField(read_only=True)
refresh_token = serializers.CharField(read_only=True)
user_type = serializers.CharField(read_only=True)
request_source = serializers.CharField(read_only=True, default='mobile')
def validate(self, data):
username_or_email = data.get('username_or_email')
password = data.get('password')
if not username_or_email or not password:
raise MyCustomException(detail={"error_message": "Must include 'username_or_email' and 'password'."}, status_code=status.HTTP_400_BAD_REQUEST)
user = authenticate(
request=self.context.get('request'),
username=username_or_email,
password=password
)
if user is None:
raise MyCustomException(detail={"error_message": "Invalid username/email or password."}, status_code=status.HTTP_400_BAD_REQUEST)
if not user.is_active:
raise MyCustomException(detail={"error_message": "User is inactive."}, status_code=status.HTTP_400_BAD_REQUEST)
if not user.email_verified:
email_otp = ''.join([str(randint(0, 9)) for _ in range(6)])
user.email_otp = email_otp
user.save()
send_registration_email.delay(
'Welcome to Your Website',
'email.html',
{'code': email_otp},
settings.EMAIL_HOST_USER,
[user.email],
)
raise MyCustomException(detail={"error_message": "Please verify your email first"}, status_code=status.HTTP_400_BAD_REQUEST)
if not user.phone_verified:
phone_otp = ''.join([str(randint(0, 9)) for _ in range(6)])
user.phone_otp = phone_otp
user.save()
raise MyCustomException(detail={"error_message": "Phone number is not verified. Please verify it first"}, status_code=status.HTTP_400_BAD_REQUEST)
request = self.context.get('request')
if request is None:
raise MyCustomException(detail={"error_message": "Request context is required."}, status_code=status.HTTP_400_BAD_REQUEST)
request_source = request.headers.get('source', 'mobile')
if request_source == 'mobile' and user.user_type != 'user':
raise MyCustomException(detail={"error_message": "Only normal users can log in from mobile."}, status_code=status.HTTP_400_BAD_REQUEST)
elif request_source == 'web' and user.user_type != 'seller':
raise MyCustomException(detail={"error_message": "Only sellers can log in from the web portal."}, status_code=status.HTTP_400_BAD_REQUEST)
if request_source == 'web':
# Redirect to dashboard
return {
'status': status.HTTP_200_OK,
'message': 'Redirect to dashboard',
'error': False,
'data': '/dashboard',
'user_type': user.user_type,
}
else:
# Return tokens for user
return self._get_tokens_for_user(user, request_source)
def _get_tokens_for_user(self, user, request_source):
refresh = RefreshToken.for_user(user)
access_token = str(refresh.access_token)
refresh_token = str(refresh)
return {
'status':status.HTTP_200_OK,
'message': 'Login successful',
'error': False,
'access_token': access_token,
'refresh_token': refresh_token,
'user_type': user.user_type,
}
class MyCustomException(PermissionDenied):
status_code = status.HTTP_400_BAD_REQUEST
default_detail = "Custom Exception Message"
default_code = 'invalid'
def __init__(self, detail=None, status_code=None):
if detail is not None:
self.detail = detail
else:
self.detail = {"error_message": self.default_detail}
if status_code is not None:
self.status_code = status_code
def render(self):
# Render the exception content
return Response(data=self.detail, status=self.status_code)
My View
class LoginView(generics.GenericAPIView):
serializer_class = LoginSerializer
def post(self, request, *args, **kwargs):
try:
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
response_data = serializer.validated_data
request_source = response_data.get('request_source')
if request_source == 'web':
return Response(
data=response_data,
status=status.HTTP_302_FOUND, # HTTP status code for redirection
headers={'Location': response_data.get('redirect_url')} # Redirection URL
)
return Response(data=response_data, status=status.HTTP_200_OK)
except MyCustomException as exc:
# If a custom exception is raised, return the error response
return Response(data={"error_message": exc.detail}, status=exc.status_code)
except Exception as e:
# Handle other exceptions
error_message = "An unexpected error occurred."
return Response(data={"error_message": error_message}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
if response is success then i get my desired response like this
{
"status": 200,
"message": "Redirect to dashboard",
"error": false,
"data": "/dashboard",
"user_type": "seller"
}
but if there is any error then i get this
ContentNotRenderedError at /api/login/
The response content must be rendered before it can be accessed.
Thank’s for your help in advance