Today we are going to build a simple app that consumes the JSON response of a simple GitHub API request. We shall be using the following technologies:
- Python/Django
- Requests
- Pipeline
- NodeJS
- Bower
That is all the technology we shall need. Python and Django will provide the framework for the application. Requests will be used to make a simple request to the Github API. NodeJS and Bower will be used for front end dependency management and Pipeline will do the asset compression.
The Github resources we shall use:
- Github API
- Primer CSS kit
- Octicons
This tutorial assumes a knowledge of virtual environments. The use of virtualenv and virtualenvwrapper is highly recommended. If you don't have these, you can install them using pip with the following commands:
$ pip install virtualenv
$ pip install virtualenvwrapper
You should then create a virtual environment. Ours will be called gitit. Get it?
$ mkvirtualenv gitit
This should activate a virtualenv called Gitit. We shall then install Django, Requests and Pipeline.
$ pip install Django==1.8.6
$ pip install requests
$ pip install django-pipeline
When you run the pip freeze
command it should show the following:
Django==1.8.6
django-pipeline==1.6.5
requests==2.9.1
wheel==0.24.0
Switch to the directory where you intend to create the project and run the command to start a project.
django-admin startproject gitit
This should give us the following directory structure
.
├── gitit
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── manage.py
This is the basic directory structure of a Django project with no apps. We shall now proceed to create directories for our static files and the templates.
cd gitit
mkdir static templates
mkdir static/js static/css
It now time to run our server just to ensure that everything is fine.
python manage.py runserver
It should run fine, but we need to run migrations to assuage the server gods so run the migrate command
python manage.py migrate
Great, now time to create the app. We shall call it yokogao
the Japanese word for profile of a face as seen from the side. This may need clarification :)
python manage.py startapp yokogao
Our structure should now have changed to this:
.
├── db.sqlite3
├── gitit
│ ├── __init__.py
│ ├── __init__.pyc
│ ├── settings.py
│ ├── settings.pyc
│ ├── urls.py
│ ├── wsgi.py
│ └── wsgi.pyc
├── manage.py
├── static
│ ├── css
│ └── js
├── templates
└── yokogao
├── __init__.py
├── admin.py
├── migrations
│ └── __init__.py
├── models.py
├── tests.py
└── views.py
It is now time to customize our settings so as to enable the app work best within the project. Let us add the app to the installed apps
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
#local apps
'yokogao',
)
We should now be ready to create the views that allow us to access the Github API and request the basic information we require for our app. For more about the information returned by the API, use Curl
curl https://api.github.com/users/raybesiga
For a simple Curl tutorial that uses the Github API, check this one out.
Please use your Github username wherever
raybesiga
is used
Edit the yokogao/views.py
file to look this way:
from django.shortcuts import render, HttpResponse
import requests
import json
def index(request):
yoko = requests.get('https://api.github.com/users/raybesiga')
content = yoko.text
return HttpResponse(content)
You should note that we import requests
and json
. Requests to query the API, and JSON to handle the JSON returned. We shall store the JSON as text in the content
variable, for now.
You should now create a URLS file at yokogao/urls.py
from django.conf.urls import url
import views
urlpatterns = [
url(r'^$', views.index, name='index'),
]
Head over to gitit/urls.py
and edit the file so as to use the Yokogao URLs for the app
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^', include('yokogao.urls')),
]
If you run your server now, you should be able to see this in your browser, albeit without format
{
"login":"raybesiga",
"id":405697,
"avatar_url":"https://avatars.githubusercontent.com/u/405697?v=3",
"gravatar_id":"",
"url":"https://api.github.com/users/raybesiga",
"html_url":"https://github.com/raybesiga",
"followers_url":"https://api.github.com/users/raybesiga/followers",
"following_url":"https://api.github.com/users/raybesiga/following{/other_user}",
"gists_url":"https://api.github.com/users/raybesiga/gists{/gist_id}",
"starred_url":"https://api.github.com/users/raybesiga/starred{/owner}{/repo}",
"subscriptions_url":"https://api.github.com/users/raybesiga/subscriptions",
"organizations_url":"https://api.github.com/users/raybesiga/orgs",
"repos_url":"https://api.github.com/users/raybesiga/repos",
"events_url":"https://api.github.com/users/raybesiga/events{/privacy}",
"received_events_url":"https://api.github.com/users/raybesiga/received_events",
"type":"User",
"site_admin":false,
"name":"Ray Besiga",
"company":"Sparkplug ",
"blog":"http://raybesiga.com",
"location":"Kampala, Uganda",
"email":"[email protected]",
"hireable":true,
"bio":null,
"public_repos":91,
"public_gists":5,
"followers":13,
"following":17,
"created_at":"2010-09-18T07:51:02Z",
"updated_at":"2016-02-04T05:30:03Z"
}
Great, we are now at the step where we can show stuff in the browser. However, there is business we need to take care of before we can even build our base template. Time to do some front end stuff. Remember the NodeJS and Bower I mentioned earlier? Yeah, now is the time to use it. Ensure you have NodeJS and NPM installed on your machine. More on that here
We shall install Bower and Yuglify, Pipeline's default JS and CSS compressor.
$ npm install -g bower
$ npm install -g yuglify
To keep things interesting, we shall use the Primer toolkit by Github. It is purposely incomplete an they do say so themselves
Heads up! We love open source, but Primer is unlikely to add new features that are not used in GitHub.com. It's first and foremost our CSS toolkit. We really love to share though, so hopefully that means we're still friends <3.
Let us proceed to use it in our app, change directory to the static/css
folder and run the following command
bower install primer-css --save
You should now have a bower_components
folder therein with the primer-css
and octicons
child directories. Time to make changes to the settings file so as to use these assets in our templates.
Change the Templates section of the settings as follows:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': ['templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
Add the following for the STATIC to comply
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
# Django Pipeline
STATICFILES_STORAGE = 'pipeline.storage.PipelineCachedStorage'
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
'pipeline.finders.PipelineFinder',
'pipeline.finders.FileSystemFinder',
'pipeline.finders.AppDirectoriesFinder',
'pipeline.finders.PipelineFinder',
'pipeline.finders.CachedFileFinder',
)
PIPELINE_CSS_COMPRESSOR = 'pipeline.compressors.yuglify.YuglifyCompressor'
PIPELINE = {
'STYLESHEETS': {
'yokogao': {
'source_filenames': (
'css/bower_components/primer-css/css/primer.css',
'css/bower_components/octicons/octicons/octicons.css',
),
'output_filename': 'css/yokogao.css',
'extra_context': {
'media': 'screen,projection',
},
},
}
}
Great, the settings are looking good, the stars should be aligned, time to collect our compressed static.
python manage.py collectstatic
The output is long but at the bottom, you should have something similar to this at the bottom:
62 static files copied to '/Users/raybesiga/Projects/gitit/static', 64 post-processed.
We shall now proceed to use the static in our templates. Change directory to the templates
folder and create a base.html
file. Mine looks something like this:
{% load pipeline %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{% block title %}Build with the Github API{% endblock %}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Building with the Github API">
<meta name="author" content="Ray Besiga">
<!-- Styles -->
{% stylesheet 'yokogao' %}
</head>
<body>
<div class="container">
{% block content %}
{% endblock %}
</div>
<!-- Javascript -->
{% block extra_scripts %}
{% endblock %}
</body>
</html>
Please note that we include {% load pipeline %}
at the top and then use {% stylesheet 'yokogao' %}
for the output stylesheet.
We shall proceed to create the templates
folder and the index.html
file for the app within the yokogao
folder.
$ mkdir yokogao/templates/yokogao
$ cd yokogao/templates/yokogao
$ touch index.html
Before we can show data in the index.html
file, we need to get the context data within the views file. Let is make those changes to our yokogao/views.py
file.
from django.shortcuts import render, HttpResponse
import requests
def index(request):
yoko = requests.get('https://api.github.com/users/raybesiga')
lisht = []
lisht.append(yoko.json())
cleanedData = []
yokogaoData = {}
for data in lisht:
yokogaoData['name'] = data['name']
yokogaoData['blog'] = data['blog']
yokogaoData['email'] = data['email']
yokogaoData['public_gists'] = data['public_gists']
yokogaoData['public_repos'] = data['public_repos']
yokogaoData['avatar_url'] = data['avatar_url']
yokogaoData['followers'] = data['followers']
yokogaoData['following'] = data['following']
yokogaoData['location'] = data['location']
yokogaoData['created_at'] = data['created_at']
yokogaoData['updated_at'] = data['updated_at']
cleanedData.append(yokogaoData)
return render(request, 'yokogao/index.html', {'data': yokogaoData})
Then edit the index.html
file
{% extends "base.html" %}
{% block title %} Github Yokogao {% endblock %}
{% block content %}
<div class="columns centered">
<div class="one-third column centered">
<h3>Basic Django app with the Github API</h3>
</div>
</div>
<div class="columns">
<div class="one-third column centered">
<img class="avatar" src="{{ data.avatar_url }}" width="300" height="300" style="border-radius: 50%;">
</div>
<div class="one-third column centered">
<p><br></p>
</div>
<div class="one-third column centered">
<nav class="menu">
<a class="menu-item" href="#">
<span class="octicon octicon-person"></span>
{{ data.name }}
</a>
<a class="menu-item" href="#">
<span class="octicon octicon-location"></span>
{{ data.location }}
</a>
<a class="menu-item" href="#">
<span class="octicon octicon-list-ordered"></span>
<span class="counter">{{ data.public_repos }}</span>
Public Repos
</a>
<a class="menu-item" href="#">
<span class="octicon octicon-bookmark" ></span>
<span class="counter">{{ data.followers }}</span>
Followers
</a>
<a class="menu-item" href="#">
<span class="octicon octicon-eye"></span>
<span class="counter">{{ data.following }}</span>
Following
</a>
<a class="menu-item " href="{{ data.blog }}" target="_blank">
<span class="octicon octicon-globe"></span>
Website: {{ data.blog }}
</a>
</nav>
</div>
</div>
<div clas="columns">
<div class="one-third column centered">
<h4>Built with <span class="octicon octicon-heart" ></span> using the Github API and Primer</h4>
</div>
</div>
{% endblock %}
Now if you run your server, you should have the browser showing your yokogao on the index page.
The project has been updated a couple of times, make sure to add the following to your local settings
GITHUB_USER = 'your_github_username'
DEBUG = True