Building a Contact Manager with Python, Flask, and HarperDB
Tags: python, tutorial, database, beginners
Published: 2021-06-02 19:45:13

# What is HarperDB?

[HarperDB](https://studio.harperdb.io/sign-up?utm_source=solomon) is an easy database solution that helps collect, distribute, and analyze data throughout your organization. It provides unmatched flexibility, speed, security, and value for every data use case your organization and project require.

# Benefits of Using HarperDB in Your Next Project

* Seamless integration into any project and tool using a straightforward REST API. It also comes with support for multiple languages via various drivers and plugins.
* HarperDB provides the ability to run your database anywhere, ranging from edge to cloud and anywhere in between.
* Support for executing complex, performant, ACID-compliant SQL queries on JSON with no data duplication.
* Functionality to search databases with JSON filters and SQL queries without the need of an ORM.
* You enjoy the flexibility of a NoSQL database with the security, consistency, and durability of an RDBMS by leveraging a dynamic schema with attribute level and role-based security in a single storage engine.
* HarperDB Studio offers a sleek and intuitive management UI that allows you to browse, query, and manage data all in one place, with no coding required.

# Getting Started with HarperDB

## Creating the HarperDB Database Instance

We need to create a database for the contact manager. If you have not created an account on HarperDB before now, create one on [HarperDB’s website](https://studio.harperdb.io/sign-up?utm_source=solomon).

In the dashboard, click on `Create New HarperDB Cloud Instance` as shown in the image below.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x20gtfhfpd6y5dgrvieg.png)

Then, select a database instance type. A HarperDB instance is where you host your database. It can either be local (user-installed instance) or configured and managed on HarperDB servers (cloud instance). In this tutorial, we will be using the cloud instance.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zdwatm8tuiuqfw5hu6cx.png)

You will need to provide information about your cloud instance, like name and authentication credentials. Click on the `Instance Details` button after supplying this information.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/36n1g53vovrx6pp79y1q.png)

> Note: Store the credentials somewhere secure and easily retrievable as we will need them in later parts of this tutorial.

You are also required to provide the specification of the cloud instance. HarperDB allows you to choose the RAM, storage size, and region your instance should have.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hc95trszs9rsncquue6u.png)

Once you have provided all the configuration details for the cloud instance, click on the `Confirm Instance Details` button, then finalize everything to create it.

> NOTE: Cloud instances take several minutes to create. You’ll need to wait throughout this process. HarperDB also sends notifications via email on the instance creation status.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a1esdhzd4ipe23zf8g18.png)

## Creating the Database Schemas

Let’s set up the necessary database `schema` for our application. A `schema` is a collection of tables in HarperDB, analogous to a database in SQL. Without schemas, you cannot store data in the database.

To create a schema, first select the cloud instance in your dashboard, navigate to the `schemas` section by the left, and then provide a name for it. In this tutorial, we will be using the name `contacts_repo` as displayed in the image below:

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fqmedmlrrsom79jm9pqa.png)

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jz4npej2r7pcz8s5s2js.png)

## Creating the Schema Tables

Let’s set up `tables` in our database schema. A `table` is analogous to `tables` in SQL databases like MySQL and `collections` in NoSQL databases like MongoDB.

To create a table. First, navigate to the `tables` section by the left side of your dashboard, then provide a name and `hash_attribute` for it. A `hash_attribute` identifies every record in the database uniquely, and it is synonymous with `Primary Keys` in a relational database.

Here, we will set the name to `contacts` and `hash_attribute` to `contact_id` as shown in the image below:

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/my0xs0o44kukw62gulny.png)

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t2vgu71r45z6v1gdlnts.png)

# Setting Up the Demo Application

## Cloning the Contact Manager Repository

For the sake of convenience, I have written the user interface of the contact manager (with Flask and Bootstrap) that we will use in this article. To get started, you will need to clone [my repository](https://github.com/LordGhostX/harperdb-contact-manager) and initialize the app like so:

```bash
git clone https://github.com/LordGhostX/harperdb-contact-manager
cd harperdb-contact-manager
```

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a4ahfl5ffpog51loy8ob.png)

The `user-interface` directory contains only the user interface of the contact manager. In contrast, the `full-application` directory contains the entire application (HarperDB + Python + Flask) that we will build in this tutorial.

## Installing the Project’s Requirements

You need to install the contact manager’s requirements before you can run it. In your terminal, type:

```bash
cd user-interface  
pip install -r requirements.txt
```

Run the application to make sure it’s working. In your terminal, type:

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ewfymxxmsotxz3gz45w5.png)

To view the user interface of our application, head to your browser and open the URL `http://127.0.0.1:5000`, you should get a response similar to the image below:

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ybmqika6sn4wvllqcm4.png)

# Integrating HarperDB with Python and Flask

Now that we have set up the base application and database schemas, let’s move to communicating with the database using Python, as shown in the [SDK documentation](https://github.com/HarperDB/harperdb-sdk-python).

## Installing HarperDB Python SDK

We need to get the Python SDK for HarperDB. It provides functionalities that allow an application to make queries to the HarperDB database instance. It’s available on pip, making it installable with a single command in the terminal.

In the terminal, type:

```bash
pip install harperdb
```

## Configuring HarperDB Python SDK

We need to import the HarperDB SDK into our Flask application to use it. To do this, add the following code to the `app.py` file:

```python
import harperdb
```

We also have to initialize the Python SDK client with the database instance authentication credentials we saved earlier. Add the following code to the `app.py` file right after initializing the Flask app.

```python
app.config["SECRET_KEY"] = "SECRET_KEY"
db = harperdb.HarperDB(
    url="HARPERDB_URL",
    username="HARPERDB_USERNAME",
    password="HARPERDB_PASSWORD"
)
```

> Note: Don’t forget to replace the credentials placeholders with the appropriate values for your application.

The `HARPERDB_URL` is present in the HarperDB dashboard, where all the database instances are displayed.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bg29y116ui5s8uc5v4i1.png)

## Testing the HarperDB Database Connection

To test our HarperDB cloud instance and credentials, we will be querying our database for its description. To do this, add the block of code below right before running the application in the `app.py` file.

```python
print(db.describe_all())
```

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/36ct1ash8a5nzjsd087a.png)

Run the `app.py` file. If you get a response like an image below, the configuration is correct. If you don’t, check if your credentials are valid and correct.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v4nt7mafk9hr5xmcpp5a.png)

# Making Queries to HarperDB

## Creating New Documents in HarperDB

To create new documents in our HarperDB schema, we need to run an `INSERT` query in the database via the Python SDK. HarperDB provides two methods to do this:

1. The SQL way: This involves running a SQL query to insert data into the database.
2. The NoSQL way: This involves using the `insert` method of the Python SDK to insert data into the database.

Here is sample Python code to demonstrate both methods:

```python
# SQL way
db.sql("INSERT INTO contacts_repo.contacts (name, email) VALUES ('LordGhostX', 'lordghostx@email.com')")

# NoSQL way
result = db.insert("contacts_repo", "contacts", [{"name": "LordGhostX", "email": "lordghostx@email.com"}])
```

> NOTE: If you omit the `hash_attribute` metadata when executing an `INSERT` query, HarperDB will automatically generate one for you and store it.

The code above executes an `INSERT` query to your HarperDB cloud database. It creates a document in the `contacts` table, in the `contacts_repo` schema with the `name` and `email` metadata.

We can integrate this into our contact manager by updating the `contacts` route with the code below:

```python
@app.route("/contacts/", methods=["GET", "POST"])
def contacts():
    if request.method == "POST":
        action = request.form.get("action")
        contact_data = {
            "name": request.form.get("name", "").strip(),
            "job": request.form.get("job", "").strip(),
            "email": request.form.get("email", "").strip(),
            "phone": request.form.get("phone", "").strip()
        }

        if action == "addContact":
            db.insert("contacts_repo", "contacts", [contact_data])
            flash("Successfully added new contact", "success")

        return redirect(url_for("contacts"))

    return render_template("contacts.html")
```

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t79id6vnfbizhvdsygww.png)

## Reading Documents from HarperDB

To read documents from our HarperDB tables, we need to run a `SELECT` or `SEARCH` query in the database via the Python SDK. HarperDB provides two methods to do this:

1. The SQL way: This involves running a SQL query to select the data from the database.
2. The NoSQL way: This involves using either the `search_by_hash` or `search_by_value` methods of the Python SDK to select data from the database.

Here is sample Python code to demonstrate both methods:

```python
# SQL way
db.sql("SELECT * FROM contacts_repo.contacts")

# NoSQL way
db.search_by_hash("contacts_repo", "contacts", ["hash_attribute"]) # returns all documents with the specified hash attributes

db.search_by_value("contacts_repo", "contacts", "name", "LordGhostX") # returns all documents with the specified values
```

The code above executes a `SELECT` and `SEARCH` query to your HarperDB cloud database. It fetches all the documents in the `contacts` table, in the `contacts_repo` schema with the specified hash attributes or values.

We can integrate this into our contact manager by updating the rendering of the `contacts` route in the `app.py` file with the code below:

```python
contacts_data = db.sql(
    "SELECT * FROM contacts_repo.contacts ORDER BY name")
return render_template("contacts.html", contacts_data=contacts_data)
```

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t3m1ceub30pqsa5t0n7o.png)

We also need to update the contacts page to render the data fetched from the HarperDB request. Update the contacts table body `<tbody>` in the `contacts.html` file with the code below:

```html
<tbody>
  {% for contact in contacts_data %}
  <tr>
    <td id="contactName-{{ contact.contact_id }}">{{ contact.name }}</td>
    <td id="contactEmail-{{ contact.contact_id }}">{{ contact.email }}</td>
    <td id="contactPhone-{{ contact.contact_id }}">{{ contact.phone }}</td>
    <td id="contactJob-{{ contact.contact_id }}">{{ contact.job }}</td>
    <td>
      <button class="btn btn-primary" data-toggle="modal" data-target="#contactModal" onclick="displayContactInfo('{{ contact.contact_id }}')">View Details</button>
    </td>
  </tr>
  {% endfor %}
</tbody>
```

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xrd46pn332eayyxusqza.png)

## Updating Documents in HarperDB

To update documents in our HarperDB tables, we need to run an `UPDATE` query in the database via the Python SDK. HarperDB provides two methods to do this:

1. The SQL way: This involves running a SQL query to update the data in the database.
2. The NoSQL way: This involves using the `update` method of the Python SDK to update data in the database.

Here is sample Python code to demonstrate both methods:

```python
# SQL way
db.sql("UPDATE contacts_repo.contacts SET email='lordghostx@newemail.com' WHERE contact_id='sample_hash_attribute'")

# NoSQL way
db.update("contacts_repo", "contacts", [{"contact_id": "sample_hash_attribute", "email": "lordghostx@newemail.com"}])
```

The code above executes an `UPDATE` query to your HarperDB cloud database. It updates the document in the `contacts` table, in the `contacts_repo` schema with the specified hash attributes with the new values supplied.

We can integrate this into our contact manager by updating the action handling in the `contacts` route with the code below:

```python
if action == "updateContact":
    contact_data["contact_id"] = request.form.get("contactID")
    db.update("contacts_repo", "contacts", [contact_data])
    flash("Successfully updated contact information", "success")
```

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c1k9ti0jt9wdumw7612o.png)

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2sqxk8a3ibf93acgx93b.png)

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ltvdxfwn5btr3tps5m5o.png)

## Deleting Documents from HarperDB

To delete documents from our HarperDB tables, we need to run a `DELETE` query in the database via the Python SDK. HarperDB provides two methods to do this:

1. The SQL way: This involves running a SQL query to delete the data from the database.
2. The NoSQL way: This involves using the `delete` method of the Python SDK to delete data from the database.

Here is sample Python code to demonstrate both methods:

```python
# SQL way
db.sql("DELETE FROM contacts_repo.contacts WHERE name='LordGhostX'")

# NoSQL way
db.delete("contacts_repo", "contacts", ["sample_hash_attribute"])
```

The code above executes a `DELETE` query to your HarperDB cloud database. It deletes the document in the `contacts` table, in the `contacts_repo` schema with the specified `hash_attribute`, or has the value `LordGhostX` in the `name` column.

We can integrate this into our contact manager by updating the `logout` route with the code below:

```python
@app.route("/contacts/delete/<string:contact_id>")
def delete_contact(contact_id):
    db.delete("contacts_repo", "contacts", [contact_id])
    flash("Successfully deleted contact information", "success")
    return redirect(url_for("contacts"))
```

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zq33tr58ggecxug58sy4.png)

# Conclusion

By integrating HarperDB with Python and Flask, we built a contact manager with CRUD functionalities with minimal effort. We saw how to create cloud databases, manage them, and execute queries using HarperDB.

The source code of the contact manager is available on [GitHub](https://github.com/LordGhostX/harperdb-contact-manager). It was exciting integrating HarperDB into a Flask application, and I can’t wait to see the amazing things you create with it!

If you have any questions, don't hesitate to contact me on Twitter: [@LordGhostX](https://twitter.com/LordGhostX)