#StackBounty: #python #python-3.x #mvc #url-routing Python (Sanic) Routing

Bounty: 50

I am new to Python and wanted to explore how I can associate routes with “controllers” with Sanic as a base. It works fine but “feels” a bit clunky but I can’t put my finger on why/how.

routes.py – Returning controller methods from a given route

from .index import IndexRoutes
from .clients import ClientRoutes
from Controllers.IndexController import *
from Controllers.ClientController import *

CLASSES = [
    IndexRoutes,
    ClientRoutes
]

def add_routes(app):
    routes = get_routes()

    for route in routes:
        for m in route['methods']:
            controller = m['controller']
            method = m['method']

            app.add_route(
                eval(controller + '.' + method),
                route['prefix'] + m['path'],
                methods=m['request_methods']
            )


def get_routes():
    routes = []

    for c in CLASSES:
        methods = getattr(c, 'ROUTE_METHODS')

        route = {
            'name': getattr(c, 'ROUTE_NAME'),
            'methods': [],
            'prefix': getattr(c, 'ROUTE_PREFIX')
        }

        for method in methods:
            route['methods'].append(getattr(c, method)())

        routes.append(route)

    return routes

client.py – Example of route definitions

class ClientRoutes:
    ROUTE_NAME = 'clients'
    ROUTE_METHODS = ['index', 'create', 'update', 'single', 'destroy']
    ROUTE_PREFIX = 'clients'


    def index():
        return {
            'controller': 'ClientController',
            'method': 'index',
            'path': '/',
            'request_methods': ['GET']
        }


    def create():
        return {
            'controller': 'ClientController',
            'method': 'create',
            'path': '/',
            'request_methods': ['POST']
        }


    def single():
        return {
            'controller': 'ClientController',
            'method': 'single',
            'path': '/<id>',
            'request_methods': ['GET']
        }


    def update():
        return {
            'controller': 'ClientController',
            'method': 'update',
            'path': '/<id>',
            'request_methods': ['PUT']
        }


    def destroy():
        return {
            'controller': 'ClientController',
            'method': 'destroy',
            'path': '/<id>',
            'request_methods': ['DELETE']
        }

ClientController.py – Example of controller

from sanic import response
from Database.Model import Model
from Database.Client import Client
from Helpers.transformers import to_dict

class ClientController:

    async def index(request):
        clients = Model(Client)
        return response.json(to_dict(clients.get()))

    async def create(request):
        data = request.json
        try:
            if 'name' not in data:
                raise KeyError('Name is required')
            else:
                if len(data['name']) < 1:
                    raise ValueError('Name is required')
        except KeyError as e:
            return response.json(str(e), 400)
        except ValueError as e:
            return response.json(str(e), 400)

        client = Model(Client)
        return response.json(to_dict(client.save(data)))

        # ... Other methods below, unnecessary for this example


Get this bounty!!!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.