0

We're using DRF for our backend. I'm trying to create a class to handle non-fatal messages throughout our system, returned as a JsonResponse - like APIException, but without raising an exception.

The idea is to be able to do something like this:

    return APIMessage("This is my message.")

...with optional args to specify/overwrite message_type, message_code, and status_code.

The first problem I ran into was that __init__ can't return a value. From this post, I found the way I should be doing it, but I now get this error...

__new__() takes 1 positional argument but 2 were given

Here's my class...

class APIMessage(object):
    default_message = None
    default_message_code = 'message'
    default_message_type = 'status'
    default_status_code = 200

    def __init__(self, message=None, message_code=None, message_type=None, status_code=None):
        if message is None:
            message = self.default_message
        if message is None:
            raise APIMessageRequired()

        if message_code is None:
            message_code = self.default_message_code

        if message_type is None:
            message_type = self.default_message_type

        self.status_code = status_code
        if status_code is None:
            self.status_code = self.default_status_code

        self.result = {
            'result': {
                'message':      message,
                'message_code': message_code,
                'message_type': message_type,
            }
        }

    def __new__(cls):
        return JsonResponse(cls.result, status=cls.status_code)

I realize it's wanting an explicit "self" arg, but from the example code in the above linked post, the __new__ method should have "cls" as its first (only?) arg.

I think this would work if I just create a utility function, but I'd rather use a class if possible.

ExTexan
  • 373
  • 2
  • 18

1 Answers1

2

Overriding __new__ is most certainly not the way to do this. It doesn't make sense to have a class that when instantiated returns something other than an instance of that class.

Two options spring to mind. One is to not use a class at all; since you just want some data wrapped in a response, you should just write a function to do that.

def api_message(message=None, message_code=None, message_type=None, status_code=None):
    ...
    return JsonResponse(result, status=status_code)

The other is to make your class inherit from drf's Response class, and pass the data into the superclass init. DRF will then do the right thing when it receives the instance.

class APIMessage(Response):
    ...
    def __init__(self, message=None, message_code=None, message_type=None, status_code=None):
        ...
        super().__init__(self.result, status=self.status_code)
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895