popolo - code simple..

popolo - code simple..

Masonite Project - FullCalendar Example Tutorial

Masonite Project - FullCalendar Example Tutorial

Theodoros Kafantaris's photo
Theodoros Kafantaris
·Apr 29, 2022·

4 min read

Table of contents

  • Masonite Installation
  • Activating Our Virtual Environment
  • Install Masonite
  • Start project
  • Start Development Server
  • Database Configuration
  • Create Migration and Model
  • Add Routes
  • Create Controller
  • Create Template Files

In this series, we will go over the demonstration of masonite fullcalendar example using ajax requests. We will create events table with title, start and edit date column. Then we can add and edit that event in our database.

Masonite Installation

mkdir fullcalendar
cd fullcalendar

Activating Our Virtual Environment

python -m venv venv
source venv/bin/activate

Install Masonite

pip install masonite

Start project

project start .

Start Development Server

python craft serve

This is it! We have the new Masonite Project running now!

Database Configuration

In this step, we will configure mysql DB in our .env. We need to add database name, mysql username and password. So we need to create in our mysql server a DB with name fullcalendar.

DB_CONNECTION=mysql
#SQLITE_DB_DATABASE=masonite.sqlite3
DB_HOST=127.0.0.1
DB_USERNAME=root
DB_PASSWORD=
DB_DATABASE=fullcalendar
DB_PORT=3306
DB_LOG=True

Create Migration and Model

In this step we will create migration for events table using Masonite command, so first fire bellow command:

python craft migration create_events_table --create events

After this step we can find one file in following path "database/migrations" and we have to put bellow code in our migration file for create events table.

"""CreateEventsTable Migration."""

from masoniteorm.migrations import Migration


class CreateEventsTable(Migration):
    def up(self):
        """
        Run the migrations.
        """
        with self.schema.create("events") as table:
            table.increments("id")
            table.string("title")
            table.date("start")
            table.date("end")
            table.timestamps()

    def down(self):
        """
        Revert the migrations.
        """
        self.schema.drop("events")

Then after, simply run migration:

python craft migrate

After we created "events" table we should create Event model for items, so first create Event.py using the following command:

python craft model Event

- app/models/Event.py

""" Event Model """

from masoniteorm.models import Model


class Event(Model):
    """Event Model"""
    __fillable__ = ["title", "start", "end"]
    __dates__ = ["start","end"]

Add Routes

We need to add routes for product crud application. So we open our "routes/web.py" file and add following route.

- routes/web.py

from masonite.routes import Route

ROUTES = [Route.get("/", "WelcomeController@show"),
          Route.get("/events/get_events", "EventController@get_events"),
          Route.get("/events/create", "EventController@create"),
          Route.post("/events/store", "EventController@store"),
          Route.get("/events/edit/@product", "EventController@edit"),
          Route.post("/events/update", "EventController@update"),
]

Create Controller

Now we will create new EventController for the methods above so first run bellow command :

python craft controller EventController

- app/controllers/EventController.py

from masonite.controllers import Controller
from masonite.request import Request
from masonite.views import View
from masonite.response import Response
from masonite.facades import Dump



from app.models.Event import Event


class EventController(Controller):
    def get_events(self):

        return Event.all()

    def index(self, view: View):
        # Dump.dd(Event.all())
        return view.render("events.index")

    def create(self, view: View, request: Request):
        date = request.input('date')
        # Dump.dd(date)
        return view.render("events.create", {'date': date})

    def edit(self, view: View, request: Request):
        event = Event.find(request.param('event_id'))
        # Dump.dd(event.serialize())
        return view.render('events.edit', {'event': event})

    def store(self, request: Request, response: Response):
        # Dump.dd(request.all())
        Event.create(request.all())
        return response.redirect('/events')

    def update(self, request: Request, response: Response):
        event = Event.find(request.input('event_id'))
        event.update(request.only('title', 'start', 'end'))
        return response.redirect('/events')

Create Template Files

- templates/events/index.html

{% extends "base.html" %}
{%block head%}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fullcalendar@5.8.0/main.css" integrity="sha256-RCJT6YvohmGy+rWQe3hpPZez8iaPnirFVfiwaBVCk1k=" crossorigin="anonymous">
<!-- Scripts -->
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@5.8.0/main.min.js" integrity="sha256-AOrsg7pOO9zNtKymdz4LsI+KyLEHhTccJrZVU4UFwIU=" crossorigin="anonymous"></script>
{% endblock %}
{% block content %}       
<div class="m-12" id='calendar'></div>
{% endblock %}
{% block js %}
<script>
    document.addEventListener('DOMContentLoaded', function() {
    var calendarEl = document.getElementById('calendar');
    var calendar = new FullCalendar.Calendar(calendarEl, {
      initialView: 'dayGridMonth',
      selectable: true,
      events: 'http://127.0.0.1:8000/events/get_events',
      eventClick: function(info) {
        window.location.replace("http://127.0.0.1:8000/events/edit/"+info.event.id);
        },
      dateClick: function(info) {
        window.location.replace("http://127.0.0.1:8000/events/create?date="+info.dateStr);
            }
    });
    calendar.render();
  });

    </script>
{% endblock %}

- templates/events/create.html

{% extends "base.html" %}

{% block content %}       
<div class="m-12">
    <h2 class="text-2xl mb-4">Create an event</h2>
    <form action="/events" method="POST">
        {{csrf_field}}
        <div class="mb-6">
        <label for="title" class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300">Title</label>
        <input type="text" name="title" id="title" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required="">
        </div>
        <div class="mb-6">
        <label for="start" class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300">Start Date</label>
        <input type="date" name="start" value={{date}} id="start" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required="">
        </div>
        <div class="mb-6">
            <label for="end" class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300">End Date</label>
            <input type="date" name="end" value={{date}} id="end" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required="">
            </div>
        <button type="submit" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">Submit</button>
    </form>
</div>   


{% endblock %}

- templates/events/edit.html

{% extends "base.html" %}

{% block content %}       
<div class="m-12">
    <h2 class="text-2xl mb-4">Edit event {{event.title}}</h2>
    <form action="/events/update" method="POST">
        {{csrf_field}}
        <input type="hidden" name="event_id" value="{{event.id}}" >
        <div class="mb-6">
        <label for="title" class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300">Title</label>
        <input type="text" name="title" id="title" value={{event.title}} class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required="">
        </div>
        <div class="mb-6">
        <label for="start" class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300">Start Date</label>
        <input type="date" name="start" value={{event.start.strftime('%Y-%m-%d')}} id="start" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required="">
        </div>
        <div class="mb-6">
            <label for="end" class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300">End Date</label>
            <input type="date" name="end" value={{event.end.strftime('%Y-%m-%d')}} id="end" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required="">
            </div>
        <button type="submit" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">Submit</button>
    </form>
</div>   


{% endblock %}

You can download the code from the repo below:

Github Repo

We did it! Now we are ready to use fullcalendar in our real projects!

 
Share this