[Banjo]
This page will serve as the extended documentation for Banjo. This page has been adapted from the offical README.md.
This documentation will walk you through building the https://cs10-email-directory.herokuapp.com, of which the code repository can be found here.
What is Banjo.
Banjo is a wrapper over Django, a Python web framework. It allows users to quickly create models with a persistant database and API.
Creating an App
Banjo can be installed with:
pip3 install django-banjo
To write a Banjo app, create a folder called app. Within app, create two files: models.py, views.py.
Throughout this documentation, the examples will refer to an personal directory server. The user will be able to add people to their directory and list out their entire directory.
Here is an example file structure:
directory_server
|
└──app
├──models.py
└──views.py
Models
Each app begins by defining the models in models.py. A model is essentially an abstracted class. Just as a class has properties, a model has fields. When defining a model’s fields, you must specify the data type.
For example, let’s consider a simple model for a Person object. A Person has a name and an email_address.
# app/models.py
from banjo.models import Model, StringField
class Person(Model):
name = StringField()
email_address = StringField()
Notice how unlike writing a Class, you do NOT need to include
self.in front of fields
[Model Field Data Types]
Banjo provides five data types for Model fields.
BooleanField(True,False)IntegerField(1,-102)FloatField(0.045,11.5)StringField("alligator","hazelnut")ForeignKey(An instance of another model)
[Database]
Once you’ve defined your models, running banjo will create a database. The db (database) is stored in database.sqlite. It will be created in the same directory as your app folder. The db allows for persistance accross usages of your model.
💻
Download DB Browser for SQLite to open the .db databse file.
This is what the Database looks like for the Person model.
| id | name | email_address |
|---|---|---|
Notice…
- the column titles are the same as the field names
- it auto generates an
idfield to distinguish between instances of the model- although it is currently empty, the rows will populate as
Persons get added
Banjo Shell
To interact with the models, you can use the Banjo shell.
banjo --shell
The Banjo shell has a ton of features, but let’s focus on:
- creating instances of the model
- viewing the model
[Create a new instance]
To create a new instance of the model:
>>> new_person = Person.from_dict({'name':'bob','email_address':'bob@minions.com'})
>>> new_person.save()
Notice, that the
from_dict()function takes adictionaryas a parameter.The
keysare the modelfieldsand thevaluesare whatever you’d like to assign to thefields.Also, notice you must save the model using
save(), or else it will not saved in the database.
👀
Re-open the .db file, and view your model in the browser.
[Viewing the models]
Now that we’ve created an instance of the model, let’s check to see it’s been successfully saved.
We can use, objects.all() to view all the models in the database:
Person.objects.all()
Views
At this point, we have a working model and have tested it using the Banjo shell.
Next you let’s define the views in views.py. The views are where you define the API functionality. Here is where you decide the endpoints are and the type of HTTP requests it will allow.
All views:
- take a
dictionarycalledparamsas a paramter - return a
dictionarywith any key,value paris
For the Directory Server, let’s implement a few simple views:
- an index view (
GET) - adding a
Person(POST) - listing all exisiting
Persons (GET) - listing one
Person’s email (GET)
[GET View]
This /index endpoint will simply return a short desciprtion of the server.
|
|
line 2- imports theclass decoratorsto write aGETorPOSTmethodline 3- imports thePersonmodel from themodels.pyfileline 5- uses aclass decoratorto define the type of HTTP request and defines the endpoint as/.line 6- defines the functionline 7- returns a dictionary
The /all_persons endpoint will return each instance of the model.
|
|
lines 3 & 9- check to see if models exisitlines 4-6- store each instance of the model in a listlines 7- returns a dictionary with thekeyas a short description and thevalueas a list of the models.
|
|
line 1-args={'name':str}- defines the payload parameter and the required data typeline 3 & 7- checks to see if the person existsline 4- stores the correct person in a variablelines 7- returns a dictionary with thekeyas the person’s name and thevalueas the person’s email.
[POST View]
Let’s start with the view for adding a Person.
|
|
line 1-args={'name': str, 'email_address': str})- defines the payload parameters and the required data typesline 7- creates an instance of the model with the payload and stores it in a variableline 8- saves the instance of the model in the databaselines 9- returns a dictionary with the model’s fields
Testing the Server
To run the server, simply type, banjo. Just make sure you’re in the same directory as the app folder.
banjo
You should see something like this:
System check identified no issues (0 silenced).
January 04, 2022 - 06:00:02
Django version 3.2.9, using settings 'banjo.settings'
Starting development server at http://127.0.0.1:5000/
Quit the server with CONTROL-C.
You now have a server running locally on your machine. You can access it just as you would on the web, however it only accessible from your computer.
[Via Terminal]
You can access your endpoints just as you did before via the command line.
To make a get request:
http get http://127.0.0.1:5000/all_persons
To make a post request
http post http://127.0.0.1:5000/add_person name='ringo' email_address='ringo@beatles.org'
[Via Web API Browser]
Banjo has a built in visual API browser. It easily allows you to access the endpoints and make GET and POST requests. It is available at the endpoint /api.
Try it out by going to the endpoint in your web browser: http://127.0.0.1:5000/api
Advanced Banjo
[Model Methods]
Similar to how when writing a class you can define its functionalities through methods, you can do the same with a Model.
For the Person object, we would like to add the functionality of tracking how many people access each entry.
First, we must add a num_accessed field to our model.
|
|
Then, we can do write a custom method to update the num_accessed field.
|
|
Notice how when using fields in a method, you MUST write
self.
We can now update our GET request to utilize the new_access() method.
|
|
In
line 5, we call the new method on the accessed person withone_person.new_access().In
line 6, we used.save()to update the instance of the model in the database.So, each time a
GETrequest is successfully called and the person exisits in the database, their corespondingnum_accessedfield is updated.