Before you try to use HarperDB in your Django project there are some trade offs you should consider. I wanna cover some of these first and then if you still decide HarperDB and Django are a fit, we’ll get into the “how to”.
If you’re reading this there’s a good chance you’re coming to this article as a participant of my August Code Battle Hackathon so I will write with those participants in mind.
Tradeoffs
I’ll start by saying that at this point in time HarperDB and Django are not exactly suited for each other. Many of the issues are similar to what I said in my video & article about why MongoDB and Django are not a fit, but luckily for HarperDB its in a much better position.
With MongoDB the biggest issue is that there is no database driver for Django and there hasn’t been a succesful implementation of converting Django queries into NoSQL queries. As a result of this, you lose A LOT of the features Django has built.
HarperDB has a simular issue. There is no database driver at the moment so we run into the same issue we had with MongoDB. In HarperDB’s case it’s a SQL & NoSQL distributed database so building this driver is not an impossible task. Lets hope they do it soon 😉
Meanwhile, consider the following:
- No more Django ORM — With no database adaptor we’ll have to use the HarperDB python package instead of the Django ORM.
-
No More Admin Panel — Without an adaptor we cant run the proper migrations we need.
-
Database Connection — The DATABASES connection object in settings.py does nothing for us without a database driver.
- No more migrations — Cant run migrations without a database driver.
- Authentication & Models — This part I am still unsure about. If we are no longer using the Django ORM, how will authentication work with the user model? This part may have to be re-written from scratch.
My Suggestion
Use FastAPI, Flask or Custom Functions.
If you choose to use a lightweight framework you’ll have the flexibility you need to make whatever database connection you want. You could also bypass building a backend all together and try using HarperDB custom functions to build an API and connect to the database directly from your frontend.
How To Guide
I’ll assume you already have a HarperDB instance setup with a ready database and a blank Django App ready to go. If not, you can follow me in setting this up in the video tutorial for this article
1 – Install HarperDB Package
You can install the HarperDB python package here. This package will give us the tools we’ll need to connect to our database and make queries.
pip install harperdb
2 – Connect to Database
Let’s make this connection in settings.py
just above the default DATABASES
object.
#settings.py
import harperdb
...
DB = harperdb.HarperDB(
url=<YOUR_HARPERDB_URL>,
username=<YOUR_HARPERDB_USERNAME>,
password=<YOUR_HARPERDB_PASSWORD>
)
3 – Query Database
We’ll start accessing data in our views by first importing the DB
variable from settings.py
and then accessing data directly.
#views.py
from django.conf import settings
db = settings.DB
def index(request):
devs = db.search_by_value('hackathon', 'developers', "id", "*", get_attributes=['*'])
context = {"devs":devs}
return render(request, 'base/index.html', context)
Now to render this data in our template you would treat it like any other queryset passed through our context dictionary.
{% for dev in devs %}
{{dev.name}}
{% endfor %}
4 – Adding CRUD
Return Single Item
def dev_profile(request, pk):
dev = db.search_by_hash('hackathon', 'developers', [pk], get_attributes=['*'])[0]
context = {"dev":dev}
return render(request, 'base/profile.html', context)
Creating Items
from django.shortcuts import render, redirect
#....
def add_profile(request):
if request.method == 'POST':
data = request.POST
db.insert('hackathon', 'developers', [{"name":data['name']}])
return redirect('index')
return render(request, 'base/form.html')
Updating Items
def update_profile(request, pk):
if request.method == 'POST':
data = request.POST
db.update('hackathon', 'developers', [{"id":pk, "name":data["name"]}])
return redirect('index')
dev = db.search_by_hash('hackathon', 'developers', [pk], get_attributes=['*'])[0]
return render(request, 'base/form.html', {"dev":dev})
Deleting Items
def delete_profile(request, pk):
if request.method == 'POST':
db.delete('hackathon', 'developers', [pk])
return redirect('index')
dev = db.search_by_hash('hackathon', 'developers', [pk], get_attributes=['*'])[0]
return render(request, 'base/delete.html', {'dev':dev})
And thats it for the demo!