CherryPy web application sample using Firebase database

  • The Firebase Realtime Database is a cloud-hosted database. Data is stored as JSON and synchronized in realtime to every connected client across different platforms. Firebase is a NoSQL database and persists data on the local storage, which enables Firebase based applications to work even when offline. The Firebase local database that persists in devices can be accessed directly from a mobile device or web browser. That means, using Firebase database we can develop web applications or mobile apps that will work on offline mode as well.

    In this tutorial we will create a python based web application using CherryPy framework. This is a simple application that lists a set of books available in a library. Users can add, edit or delete from this list. We will learn how to set up a Firebase database, connect to Firebase from a python CherryPy web application, perform basic Read, Create, Update and Delete (CRUD) operations on a Firebase DB. firebase_admin library is used as the adapter to interact to Firebase DB from python.

  • Set up python in your machine

    Download and install the latest version of python from Python Website.

    Setting up virtual environment is not a must, but its is good to keep all your projects within a virtual environment. Here, we will proceed with a virtual environment.

    For that, go to the command prompt and cd to the folder where you are going to keep your project.
    Run command python -m venv book_library to create a virtual environment folder book_library. We will be keeping all our code in this folder and the installed package files will also be kept automatically within this folder.

    Now, activate the VE using command:

    For Windows:
    book_library\Scripts\activate.bat
    For Linux, macOS:
    source book_library /bin/activate

    After VE activation, from cmd type cd book_library to navigate to the project folder.

  • Install CherryPy and Jinja2 Template Engine

    To install CherryPy, run command pip install CherryPy or pip3.9 install CherryPy
    If not working use commands:

    For Windows:
    py -3.9 -m pip install CherryPy
    For Linux, macOS:
    python3.9 -m pip install CherryPy

    Also install Jinja2 using the command pip install Jinja2.
    Jinja2 is basically a template engine that helps in serving the html to the user. Using this library along with CherryPy helps in faster development. For example, we are using Jinja2 function get_template to render HTML page from the python code and python codes like for loops are added to the HTML page using the Jinja2 template markup syntax.

  • Install firebase-admin

    For Firebase connection we are going to use the firebase-admin library. Install this using the command: pip install firebase-admin or pip3.9 install firebase-admin (If using 3.9 python version).

    Run pip freeze or pip3.9 freeze to check if all packages installed successfully.

  • Web Application Initial Setup

    Let us start with the initial set of code that is required for every CherryPy web applications. Create a file named books.py (you can provide any name) inside book_library folder and copy below code to it. books.py is going to contain your start-up code which is required to run the web app.
    Now, from command prompt navigate to book_library folder and execute command py books.py or python books.py or py -3.9 -m books or python3.9 -m books (Based on the Python version used and the Operating System).

    import cherrypy
    
    class BookLibrary(object):
        @cherrypy.expose
        def index(self):
            return 'Book Library app is starting up'
    
    if __name__ == '__main__':
        cherrypy.quickstart(BookLibrary())
    

    This code imports cherrypy module and then a startup class is created and initiated using the quickstart method from the __main__. Startup class should have a method named index that will load the first HTML content.
    In command prompt, we will see the below message when execution starts without any issues.

    	[08/Jun/2022:18:11:50] ENGINE Listening for SIGTERM.
    	[08/Jun/2022:18:11:50] ENGINE Bus STARTING
    	CherryPy Checker:
    	The Application mounted at '' has an empty config.
    
    	[08/Jun/2022:18:11:50] ENGINE Started monitor thread 'Autoreloader'.
    	[08/Jun/2022:18:11:50] ENGINE Serving on http://127.0.0.1:8080
    	[08/Jun/2022:18:11:50] ENGINE Bus STARTED
    

    Copy the URL http://127.0.0.1:8080 to your browser and run. The message Book Library app is starting up will display in the web browser, if the set up is proper and without any issues.

  • Setting up First page

    Now we are going to load an HTML file as the first page of the application.
    Create an HTML file bookslist.html inside book_library folder.

    Add below code to bookslist.html page.
    In books.py, add the line return open('bookslist.html') inside index function to render this HTML as the first page.

    Changes are automatically compiled and on refreshing the web page we can see the HTML page as the output.

  • Firebase Database Initial Setup

    To connect to a Firebase database, we have to configure Firebase project and database from the Firebase console and generate a private key configuration file.
    If you are not familiar with the process, refer page Setting up Firebase database for the first time.

  • Inserting initial set of data to the Firebase Database

    Add a new file initialdata.py within the same virtual environment and paste the below code.
    Copy the configuration file that we downloaded from the previous step to the virtual environment folder and rename it to bookslibrary-admin-key.json. Also copy your database URL from Firebase console and paste it in the code.

    In the code, we are importing firebase_admin library and then connecting to the Firebase database using the private key configuration file. Then, we are declaring a new collection BooksTable (this is similar to a table in SQL based databases) and inserting 5 records to this.

    Execute the code using the command py initialdata.py

    Copied
    import firebase_admin
    from firebase_admin import credentials
    from firebase_admin import db
    
    cred = credentials.Certificate("bookslibrary-admin-key.json")
    firebase_admin.initialize_app(cred, {
        "databaseURL": "https://projectname-xxxxxxxxxxx-rtdb.firebaseio.com/" #Your database URL
    })
    
    dbref = db.reference("BooksTable")
    dbref.push( { "ID": 1, "Name": "Harry Potter", "Year": 2020, "Price": 100 } )
    dbref.push( { "ID": 2, "Name": "The Lord of the Rings", "Year": 2018, "Price": 80 } )
    dbref.push( { "ID": 3, "Name": "The Alchemist", "Year": 2010, "Price": 85 } )
    dbref.push( { "ID": 4, "Name": "The Da Vinci Code", "Year": 2017, "Price": 70 } )
    dbref.push( { "ID": 5, "Name": "The Twilight Saga", "Year": 2015, "Price": 90 } )
    
    print(dbref.get())
    

    dbref.get() fetches the inserted records from the collection. You can see that a unique key also got generated automatically for each inserted record. This key is required to identify records while update, delete, etc.

    Copied
    {
    	'-N3w9V6DgdBXn3eYV4S2': {'ID': 1, 'Name': 'Harry Potter', 'Price': 100, 'Year': 2020},
    	'-N3w9VBcxfkrsSHZyLVZ': {'ID': 2, 'Name': 'The Lord of the Rings', 'Price': 80, 'Year': 2018},
    	'-N3w9VGh6kLhAkhO-mA9': {'ID': 3, 'Name': 'The Alchemist', 'Price': 85, 'Year': 2010},
    	'-N3w9VLhw_EZmUJiwXTe': {'ID': 4, 'Name': 'The Da Vinci Code', 'Price': 70, 'Year': 2017},
    	'-N3w9VQw0aZtLbq-vFEC': {'ID': 5, 'Name': 'The Twilight Saga', 'Price': 90, 'Year': 2015}
    }
    
  • Read data from Firebase and list

    bookslist.html is going to hold the list of books in the library. To list the items, add below code to the body of the HTML and modify books.py main method as below.
    In python file, we are imorting firebase-admin library and using its different methods establishing a connection to the Firebase DB. Note that the connection should be established only once. So we are calling the connectDB() only once at the time of initializing from __main__ method.
    In html, we are looping through the items and list it as table rows. Copy the below HTML and paste it to the body of bookslist.html.

    For styling we will use Bootstrap 5. Add below 2 lines inside head of html.

    
        <link rel="stylesheet" crossorigin="anonymous"
    	href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" >
        
    	<script crossorigin="anonymous"
    	src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" >
    	</script>
    
    

    On reload, we will get below output window.

    CherryPy and Firebase - List Items
  • Create or update record

    Add a new link button in the bookslist.html above the table.

        <a class="btn btn-primary" href="openaddbookpage/0">Add New Book</a>
    

    Add new html file, addbook.html and place the below code.
    Add two links for edit and delete in bookslist.html as below.
    Add two more route methods, openaddbookpage() and savebookdetails() in books.py below index() method to handle routing to the edit page and saving the data (Double check the pasted contents are properly intended).

    Add New Book button in the list page calls openaddbookpage route with ID as 0. So Book Details page opens in Create mode with empty text boxes.
    Edit link next to each row also calls openaddbookpage route, but passes ID number to the Book Details page. So the details of the selected book gets fetched from the DB and bind to the corresponding text boxes in the HTML page.

    savebookdetails route is called on Submit button click. If the entered ID number doesn't exist in the database, new book gets added using push() method. Otherwise, existing record is updated using update() method. To update a record, we need the unique key value that was automatically generated at the time of insert. To get this, we are looping through the records and using the selected ID, we are retrieving and storing the key at the time of page load (GET).

    CherryPy and Firebase - Add an Item
  • Delete a Record

    For delete, add a new route method deletebook(), get the unique key and call delete() method as below.

    Copied
        @cherrypy.expose
        def deletebook(self, id=0):
            bookstable = dbconn.get()
            for key, value in bookstable.items():
                if(value["ID"] == int(id)):
                    deletekey = key
                    break
            delitem = dbconn.child(deletekey)
            delitem.delete()
            raise cherrypy.HTTPRedirect("../")
    
  • CherryPy CRUD with Firebase database - Complete code

    Complete code is placed below.

Absolute Code Works - Python Topics