DEV Community

loading...
Cover image for Building a Debt Tracker with Python and Fauna

Building a Debt Tracker with Python and Fauna

LordGhostX
Everyone's Friendly Neighbourhood Ghost | Python Developer | Developer Advocate
・5 min read

Written in connection with the Write with Fauna program.

This article focuses on exploring Fauna’s CRUD capabilities to build a Python web application for managing debts. We will be creating a debt manager that provides functionalities for keeping track of debts users have incurred using Python and Flask.

Fauna is a flexible, developer-friendly, transactional cloud database delivered as a secure Data API that provides two interfaces: GraphQL and the Fauna Query Language (FQL). It includes functionality to store collections, indexes, and other databases (multi-tenancy). To learn more about Fauna, visit the official documentation.

Note: The rest of this article assumes you have a fair understanding of Fauna, Python, and Flask. For an in-depth tutorial on serverless databases and Fauna, check out my Fauna intro tutorial first.

Setting Up the Fauna Database

Create the Fauna Database

We need to create the database for the debt manager in Fauna’s dashboard. If you have not created an account on Fauna before now, create one on Fauna’s website.

In the dashboard, click on the NEW DATABASE button, provide a name for the database then press the SAVE button.

Create the Database Collections

Now, we need to create a Fauna collection to store data collected in the recently created database. A collection is similar to SQL tables containing similar characteristics, e.g., a user collection with information about users in the database.

To create a collection:

  • navigate to the Collections tab on the Fauna sidebar (left side of the screen)
  • click on the NEW COLLECTION button
  • provide a name for the collection
  • press the SAVE button

Create the Collection Indexes

We need to create an index for the collection of the database. A Fauna index allows us to browse through data stored in a database collection based on specific attributes.

To create an index:

  • move to the Indexes tab on the Fauna sidebar (left side of the screen)
  • click on the NEW INDEX button and provide the necessary information
  • press the SAVE button.

Generate Database Security Key

Finally, we need to create a Security Key to connect the database to the application. Go to the Security tab on the Fauna sidebar (left side of the screen), click the NEW KEY button, provide the necessary information, and then press the SAVE button.

Once you have done this, Fauna will present you with your Secret Key. Copy the key immediately and store it somewhere easily retrievable because it will only be displayed once.

Downloading the Demo Application

Clone the Project Repository

For the sake of convenience, I have written a Flask application with a Bootstrap user interface that we will use in this article. To get started, we need to clone my repository and initialize the application like so:

git clone https://github.com/LordGhostX/fauna-debt-tracker   
cd fauna-debt-tracker
Enter fullscreen mode Exit fullscreen mode

Install the Project Requirements

We need to install the external libraries required by the application before we can run it. In the terminal, type:

pip install -r requirements.txt
Enter fullscreen mode Exit fullscreen mode

Finally, run the application to make sure it’s working. In the terminal, type:

python3 app.py
Enter fullscreen mode Exit fullscreen mode

Configuring the Project Settings

To configure the project, open the app.py file and replace the FAUNA_SECRET_KEY placeholder variable with the Security Key generated earlier. You can also change the application’s SECRET KEY or fetch these values using environment variables.

Integrating Fauna into Python and Flask

For the debt manager, we will explore the four basic operations of persistent storage, Create (C), Read (R), Update (U), and Delete (D), using Fauna.

Creating New Documents in Fauna

In our add_loan route, we used Fauna’s Create function to store the collected loan data in our database’s loans collection.

@app.route("/loans/add/", methods=["POST"])
def add_loan():
    name = request.form.get("name")
    amount = request.form.get("amount")
    date = request.form.get("date")

    loan_data = client.query(
        q.create(
            q.collection("loans"), {
                "data": {
                    "name": name,
                    "amount": float(amount),
                    "pending": True,
                    "date_created": datetime.strptime(date, "%Y-%m-%d").astimezone(tz=tz.tzlocal())
                }
            }
        )
    )

    flash("You have successfully added loan information!", "success")
    return redirect(url_for("loans"))
Enter fullscreen mode Exit fullscreen mode

The Create function adds a new document to a collection. It takes a collection_ref parameter which indicates what collection we should create the document, and a param_object parameter which contains the document data and optional metadata.

Reading Documents from Fauna

In our loans route, we used Fauna’s Paginate function to retrieve the references of stored loans in our database, then the Get function to query the data of each document with their Reference.

@app.route("/loans/")
def loans():
    loans = client.query(
        q.paginate(
            q.match(q.index("loans_by_pending"), True),
            size=100_000
        )
    )
    loans_data = [
        q.get(
            q.ref(q.collection("loans"), loan.id())
        ) for loan in loans["data"]
    ]
    return render_template("loans.html", loans_data=client.query(loans_data))
Enter fullscreen mode Exit fullscreen mode

Updating Documents in Fauna

In our update_loan route, we used Fauna’s Update function to update the loan amount of documents in our collection. The Update function takes a Reference parameter which indicates the document to be updated, and a param_object parameter which contains the document data to update.

@app.route("/loans/update/", methods=["POST"])
def update_loan():
    action = request.form.get("action")
    amount = request.form.get("amount")
    loan_id = request.form.get("loanID")

    loan_data = client.query(
        q.get(
            q.ref(q.collection("loans"), int(loan_id))
        )
    )

    old_amount = loan_data["data"]["amount"]
    if action == "Borrow More":
        new_amount = old_amount + float(amount)
    elif action == "Repay Loan":
        new_amount = old_amount - float(amount)

    client.query(
        q.update(
            q.ref(q.collection("loans"), int(loan_id)), {
                "data": {
                    "amount": new_amount
                }
            }
        )
    )

    flash("You have successfully updated loan information!", "success")
    return redirect(url_for("loans"))
Enter fullscreen mode Exit fullscreen mode

Deleting Documents from Fauna

In our clear_loan route, we used Fauna’s Delete function to delete a document from the database with a specified Reference. The Delete function removes a document. This includes user-created documents, plus system documents for Collections, Indexes, Databases, etc.

@app.route("/loans/clear/<int:loan_id>/")
def clear_loan(loan_id):
    client.query(
        q.delete(
            q.ref(q.collection("loans"), loan_id)
        )
    )

    flash("You have successfully cleared loan information!", "success")
    return redirect(url_for("loans"))
Enter fullscreen mode Exit fullscreen mode

Conclusion

In this article, we built a debt tracker with Fauna's serverless database and Python. We saw how easy it is to integrate Fauna into a Python application and got the chance to explore some of its core features and functionalities.

The source code of the debt manager is available on GitHub. If you have any questions, don't hesitate to contact me on Twitter: @LordGhostX

Discussion (0)