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
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
Finally, run the application to make sure it’s working. In the terminal, type:
python3 app.py
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"))
The
Create
function adds a new document to a collection. It takes acollection_ref
parameter which indicates what collection we should create the document, and aparam_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))
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"))
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"))
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
Top comments (0)