Source code for ussd.screens.custom_screen

from ussd.core import UssdHandlerAbstract, UssdHandlerMetaClass
from ussd.screens.serializers import UssdBaseSerializer
from rest_framework import serializers
from ussd.utilities import str_to_class


class CustomScreenSerializer(UssdBaseSerializer):
    screen_obj = serializers.CharField(max_length=255)

    @staticmethod
    def validate_screen_obj(value):
        try:
            screen_obj = str_to_class(value)
        except Exception as e:
            raise serializers.ValidationError(str(e))
        else:
            if not isinstance(screen_obj, UssdHandlerMetaClass):
                raise serializers.ValidationError(
                    "Screen object should be of type UssdHandlerAbstract"
                )
            return screen_obj

    def validate(self, data):
        data = super(CustomScreenSerializer, self).validate(data)
        screen_obj = data['screen_obj']
        if hasattr(screen_obj, 'serializer'):
            validation = screen_obj.serializer(data=self.initial_data,
                                               context=self.context)
            if not validation.is_valid():
                raise serializers.ValidationError(validation.errors)
        return data


[docs]class CustomScreen(UssdHandlerAbstract): """ If you have a particular user case that's not yet covered by our existing screens, this is the screen to use. This screen allows us to define our own ussd screen. To create it you need the following fields. 1. screen_object This is the path to be used to import the class 2. serializer (optional) This if you want to be validating your screen with specific fields 3. You can define any field that you feel your custom screen might need. EXAMPLE: examples of custom screen .. code-block:: python class SampleCustomHandler1(UssdHandlerAbstract): abstract = True # don't register custom classes @staticmethod def show_ussd_content(): # This method doesn't have to be static # Do anything custom here. return UssdResponse("This is a custom Handler1") def handle_ussd_input(self, ussd_input): # Do anything custom here print(ussd_input) # pep 8 for the sake of using it. return self.ussd_request.forward('custom_screen_2') class SampleSerializer(UssdBaseSerializer, NextUssdScreenSerializer): input_identifier = serializers.CharField(max_length=100) class SampleCustomHandlerWithSerializer(UssdHandlerAbstract): abstract = True # don't register custom classes serializer = SampleSerializer @staticmethod def show_ussd_content(): # This method doesn't have to be static return "Enter a digit and it will be doubled on your behalf" def handle_ussd_input(self, ussd_input): self.ussd_request.session[ self.screen_content['input_identifier'] ] = int(ussd_input) * 2 return self.ussd_request.forward( self.screen_content['next_screen'] ) example of defining a yaml .. literalinclude:: .././ussd/tests/sample_screen_definition/valid_menu_screen_conf.yml """ screen_type = "custom_screen" serializer = CustomScreenSerializer def handle(self): # Todo initiate the class in the core. to avoid double changing # if the parameter changes. # calling the custom screen handler method return str_to_class( self.screen_content['screen_obj'] )( self.ussd_request, self.handler, self.screen_content, initial_screen={}, ).handle()