Skip to content
Django application
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.

Build Status codecov


  1. Swagger and coreapi for api documentations and schemas drf_yasg.
  2. Custom user model, and using email instead of username to authenticate users django-use-email-as-username.
  3. Token authentications using knox.
  4. Custom serializers and LoginView, more details in Authentication.
  5. Django model signals and Async Tasks with celery and redis, a db backend with django-celery-results.
  6. Database Factories using factory_boy .
  7. Docker with docker-compose and docker-compose override docker-compose extend for nginx, uwsgi, postgresql, django and redis
  8. Unit and integrations testing.
  9. TravisCI build .travis.yml for continuous integrations and codecov for code coverage.
  10. Grouping of config files by staging in requirements/ and wall.settings/ 12factor config.
  11. Bash script for automation to manage configurations files like settings and requirements.
  12. PEP 8 with autopep8 and flake8 for code standard.
  13. Internationalization and localizations with english and arabic, using ugettext_lazy to translate statics.
  14. CORS Cross-Origin Resource Sharing with django-cors-headers
  15. Django admin support for all the models.
  16. Environment variables using django-environ.


  1. docker and docker-compose.
  2. virtualenv.
  3. python 3.6 lts. (Tested against python 3.6 and 3.7-dev).
  4. Bash.


Production build Using docker-compose [nginx, uwsgi, postgresql, redis, django]:

   # clone the repo
   $ git clone
   $ cd django_wall
   # Run the automation script.
   # to bundle configs and start docker-compose
   $ ./scripts/start -e prod -p wall -d

Then head to: http://localhost/api/docs/ nginx reverse proxy.

To start django locally from a virtualenv, docker-compose is required for db and redis containers:

   $ mkdir wall_project

   $ cd wall_project

   $ virtualenv venv

   $ source venv/bin/activate

   $ git clone

   $ cd django_wall

   $ pip install -r requirements/local
   # bundle configs and start docker in background
   $ ./scripts/start -e local -p wall -d &
   # start celery in background
   $ celery -A wall worker -l info &
   # Migrate and run Werkzeug server.
   $ python migrate && python runserver_plus

Then head to: http://localhost:8000/api/docs/ Werkzeug for development and debugging server using django-extensions.

API and EndPoints:

API documentations:

coreapi with swagger /api/docs/.

AUTH routes:

POST api/auth/login user login AUTH.

POST api/auth/logout user logout AUTH post request with an empty body to clear current token.

POST api/auth/logout-all user logout AUTH post request with an empty body clear all users tokens.

POST api/auth/register user registration AUTH. (Attached to django signals wall_auth.signals.send_welcome_email and wall_auth.tasks.welcome_email celery task).

GET api/auth/me/<uuid> user profile.

Wall routes:

GET /api/messages/ list all wall messages.

POST /api/messages/ add new message.

GET /api/messages/<uuid>/ get message by uuid.

PUT /api/messages/<uuid>/ update message by uuid.

DEL /messages/<uuid>/ del message by uuid.

Consuming endpoint using httpie:

Installing httpie:

pip install httpie

Register user:

http POST http://localhost:8000/api/auth/register password=mypassword

Login user:

http POST http://localhost:8000/api/auth/login password=mypassword

will response with user token example: { "token": "71d5818eb2cf2ab6c464664b129484b316e48f0c6506dca7bfe2b1fdec1c2c33" }

POST new message:

http POST http://localhost:8000/api/messages/ "Authorization: Token 71d5818eb2cf2ab6c464664b129484b316e48f0c6506dca7bfe2b1fdec1c2c33" content="my content" permission="public"

will response with message data and uuid. ex: 8e29e344-107f-4340-a017-e741a75faf3d will be used for other operations.

Update message:

http PUT "http://localhost:8000/api/messages/8e29e344-107f-4340-a017-e741a75faf3d/" "Authorization: Token 71d5818eb2cf2ab6c464664b129484b316e48f0c6506dca7bfe2b1fdec1c2c33" content="Updating my contetn"

GET all messages (allowed for anon and auth user, only public messages will be listed):

http GET http://localhost:8000/api/messages/

DELETE message:

http DELETE "http://localhost:8000/api/messages/8e29e344-107f-4340-a017-e741a75faf3d/" "Authorization: Token 71d5818eb2cf2ab6c464664b129484b316e48f0c6506dca7bfe2b1fdec1c2c33"

Async task with celery:

Using celery with redis to handle email tasks.


Default: IsAuthenticated


  • ObjectOwnerPermission: Custom Permission to allow only owner of the object to 'PUT', 'DELETE', 'PATCH', used in MessageViewSet.
  • OwnerOrAdminPermission: Custom Permission to allow only owner of the object and admins, used in UserDetailView.


Token based authentication using knox

Knox authentication is token based, similar to the TokenAuthentication built in to DRF. However, it overcomes some problems present in the default implementation:

DRF tokens are limited to one per user. This does not facilitate securely signing in from multiple devices, as the token is shared. It also requires all devices to be logged out if a server-side logout is required (i.e. the token is deleted). Knox provides one token per call to the login view - allowing each client to have its own token which is deleted on the server side when the client logs out. Knox also provides an option for a logged in client to remove all tokens that the server has - forcing all clients to re-authenticate. DRF tokens are stored unencrypted in the database. This would allow an attacker unrestricted access to an account with a token if the database were compromised. Knox tokens are only stored in an encrypted form. Even if the database were somehow stolen, an attacker would not be able to log in with the stolen credentials. DRF tokens track their creation time, but have no inbuilt mechanism for tokens expiring. Knox tokens can have an expiry configured in the app settings (default is 10 hours.)

Allowing email authentication instead of username.

A combination of a custom AuthTokenSerializer and knox login in wall_auth.api.AuthTokenSerializer.

Custom user model in wall_auth.models.User

Replacing the default username behaviour with email and adding an automated username creation, validations on username happens in a custom UserSerializer in wall_auth.api.serializers.

Build and settings structure:

1.Settings structure:

Following the 12factor grouping of config files by staging(environments).

12factor config

wall/settings/ auto generated file.

wall/settings/ base settings file

wall/settings/ settings file for local env

wall/settings/ settings file for prod env

wall/settings/ settings file for test env

2.Environment variables structure:

.env auto generated file.

.env.local local environment file. prod environment file.

.env.test test environment file.

.env.docker used for docker.

  1. Docker compose structure:

docker-compse.yml base services for db and redis.

docker-compose.local.yml local updates on db and redis to forward ports. prod setting, adding django service, disable all forwaded ports except for nginx port 80.

A modified version of wait_for_postgresql script to use django-environ instead of os.env

4.Automation script:

To align stages(environments) files in one single file, scripts/start will take the environment variable with a required argument -p
for project directory and create a single point for the grouped files in wall/settings/, .env, requirements/ and docker-compose_override

usage: ./scripts/start [-epdh]
  -e --env           APP_ENV
  -p --project       Project directory
  -d --docker        Enable docker
  -h                 Display help

ex: ./scripts/start -e local -p wall -d

will create the following:

  • .env file from .env.local
  • file from
  • docker-compose.override.yml file from docker-compose_override.local.yml.
  • requirements file from requirements/local.
You can’t perform that action at this time.