Controllers

Introduction

Controllers are a vital part of Masonite and is mainly what differs it from other Python frameworks which all implement the MVC structure differently. Controllers are simply classes with methods. These methods take a self parameter which is the normal self that Python methods require. Controller methods can be looked at as "function based views" if you are coming from Django as they are simply methods inside a class and work in similar ways.

Controllers have an added benefit over straight function based views as the developer has access to a full class they can manipulate however they want. In other words, controller methods may utilize class attributes, private methods and class constructors to break up and abstract logic. They provide a lot of flexibility.

Creating a Controller

Its very easy to create a controller with Masonite with the help of our craft command tool. We can simply create a new file inside app/http/controllers, name the class the same name as the file and then create a class with methods. We can also use the craft controller command to do all of that for us which is:

terminal
$ python craft controller Dashboard

When we run this command we now have a new class in app/http/controllers/DashboardController.py called DashboardController. By convention, Masonite expects that all controllers have their own file since it’s an extremely easy way to keep track of all your classes since the class name is the same name as the file. This is very opionated but you can obviously put this class wherever you like.

Notice that we passed in Dashboard but created a DashboardController. Masonite will always assume you want to append Controller to the end.

Exact Controllers

Remember that Masonite will automatically append Controller to the end of all controllers. If you want to create the exact name of the controller then you can pass a -e or --exact flag.

terminal
$ python craft controller Dashboard -e

or

terminal
$ python craft controller Dashboard --exact

This will create a Dashboard controller located in app/http/controllers/Dashboard.py

Resource Controllers

Resource controllers are controllers that have basic CRUD / resource style methods to them such as create, update, show, store etc. We can create a resource controller by running:

terminal
$ python craft controller Dashboard -r

or

terminal
$ python craft controller Dashboard --resource

this will create a controller that looks like:

app/http/controllers/DashboardController.py
""" A Module Description """

class DashboardController:
 """Class Docstring Description
 """

    def show(self):
        pass

    def index(self):
        pass

    def create(self):
        pass

    def store(self):
        pass

    def edit(self):
        pass

    def update(self):
        pass

    def destroy(self):
        pass

Defining a Controller Method

Controller methods are very similar to function based views in a Django application. Our controller methods at a minimum should look like:

app/http/controllers/DashboardController.py
def show(self):
    pass

If you are new to Python, all controller methods must have the self parameter. The self parameter is the normal python self object which is just an instance of the current class as usual. Nothing special here.

Container Resolving

All controller methods and constructors are resolved by the container so you may also retrieve additional objects from the container by specifying them as a parameter in the method:

app/http/controllers/DashboardController.py
from masonite.request import Request
...

def show(self, request: Request):
    print(request) # Grabbed the Request object from the container

or by specifying them in the constructor:

app/http/controllers/DashboardController.py
from masonite.request import Request

class DashboardController:

    def __init__(self, request: Request):
        self.request = request

    def show(self):
        print(self.request) # Grabbed the Request object from the container

If you need a class in multiple controller methods then it is recommended to put it into the constructor in order to keep the controller DRY.

This might look magical to you so be sure to read about the IOC container in the Service Container documentation.

It’s important to note that unlike other frameworks, we do not have to specify our route parameters as parameters in our controller method. We can retrieve the parameters using the request.param('key') class method.

Read about how to create and use views by reading the Views documentation

Returning JSON

You can return JSON in a few different ways. The first way is returning a dictionary which will then be parsed to JSON:

app/http/controllers/DashboardController.py
def show(self):
    return {'key': 'value'}

you may return a list:

app/http/controllers/DashboardController.py
def show(self):
    return ['key', 'value']

Or you may even return a model instance or collection. Take these 2 code snippets as an example:

app/http/controllers/DashboardController.py
from app.User import User

def show(self):
    return User.find(1)

or

app/http/controllers/DashboardController.py
from app.User import User

def show(self):
    return User.where('active', 1).get()

Passing Route Parameters

Optionally you can pass route parameters along with your resolving code. This is useful to keep a nice clean codebase.

For example, these two code snippets are the same:

app/http/controllers/DashboardController.py
from masonite.request import Request
from masonite.view import View
...

def show(self, request: Request, view: View):
    return User.find(request.param('user_id'))

And this:

app/http/controllers/DashboardController.py
from masonite.view import View
...

def show(self, user_id, view: View):
    return User.find(user_id)

You can specify parameters along with any other container resolving.

Single Action Controllers

You can also create single action controllers.

These controllers have a single method:

class ActionController(Controller):

    def __call__(self):
        pass

Then in your routes file you can just add the controller name:

ROUTES = [
    Get('/some/route', 'ActionController')
]

And Masonite will know to call the __call__ method.

Last updated