[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
id
field to distinguish between instances of the model- although it is currently empty, the rows will populate as
Person
s 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 adictionary
as a parameter.The
keys
are the modelfields
and thevalues
are 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
dictionary
calledparams
as a paramter - return a
dictionary
with 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
Person
s (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 decorators
to write aGET
orPOST
methodline 3
- imports thePerson
model from themodels.py
fileline 5
- uses aclass decorator
to 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 thekey
as a short description and thevalue
as 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 thekey
as the person’s name and thevalue
as 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
GET
request is successfully called and the person exisits in the database, their corespondingnum_accessed
field is updated.