Rapid learning process for people with tight schedules. Implementation of the Leitner system using flash cards.
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.



Rapid learning process for people with tight schedules. Implementation of flash cards in Python 3 and Django.

Build Status


Implementation of the Leitner system

Improve your learning effectiveness using the Leitner system. It uses a simple algorithm that asks you for cards in the first areas more frequently. Correctly answered cards are moved to the next area. Incorrectly answered cards are moved back to the previous area ("defensive mode") or first area ("strict mode").

Collaborative categories

Organize your flash cards in categories and find faster what you're looking for. You can even share your categories with your classmates!

Flash cards with hints

You don't have any clue what your flash card is talking about? No problem, just write short clues and display them if you need to.

Responsive interface

Use these features on your mobile phone or tablet as well!


Create personalized user accounts for your friends with their own categories and cards.


If you intend to migrate your existing cards, just use the /api/v1/categories/ and /api/v1/cards/ endpoints.



Docker setup

docker pull joeig/memodrop:latest
docker run -d -P --name memodrop joeig/memodrop:latest
docker exec -ti memodrop python manage.py createsuperuser
docker port memodrop

This commands are starting a standalone web service with a local SQlite database in development mode. This is the quickest way to get memodrop running.

In this case, the database file is part of the container volume. If you remove the container, obviously, your data will be removed as well. Also, this setup doesn't work well if you expect more than a few concurrent users. It should never run anywhere else than on localhost.

Production usage

You should provide a custom settings file in memodrop/settings/production.py (template: production.py.dist) containing the configuration for an external DBMS like PostgreSQL or MySQL and your own secret key.

The following guide is using Django's development server again, so consider using Gunicorn, uWSGI or mod_wsgi (WSGI interface: memodrop.wsgi:application, memodrop/wsgi.py). The static assets should rather be served by a webserver like nginx rather than WSGI (use python manage.py collectstatic).

Enable your custom settings as following:

docker run -d -P --name memodrop \
  -v /path/to/your/production.py:/usr/src/app/memodrop/settings/production.py:ro \
  -e DJANGO_SETTINGS_MODULE=memodrop.settings.production \

docker exec -ti memodrop python manage.py createsuperuser
docker port memodrop

Manual setup

  1. Install Python 3.6
  2. You may want to create a virtual environment now.
  3. Install the dependencies: python setup.py install
  4. Production preparation: Copy memodrop/settings/production.py.dist to memodrop/settings/production.py and adjust the values
  5. Create a database or let Django do that for you (it will choose SQLite3 by default)
  6. Migrate the database: python manage.py migrate [--settings memodrop.settings.production]
  7. Create a super-user account: python manage.py createsuperuser [--settings memodrop.settings.production]
    • Start the application with its WSGI interface memodrop/wsgi.py
    • Alternative for developers: Start the standalone web service: python manage.py runserver [--settings memodrop.settings.production]

Create regular user accounts

You can do this with super-user permissions in Django's administration interface (/admin/).

API Authorization

The API needs a user-specific token to authorize requests. This is accomplished by dispatching an Authorization: Token <token> header with all API requests.

Tokens are user-specific and can be optained by perfoming a POST request containing the username and password to the authorization endpoint /api/v1/auth-token/. Example:

$ curl -X POST --data "username=<username>&password=<password>" ""
    "token": "091c4c1204422cb682cc9426d097d492a56a2013"

High-traffic environments

Enable distributed queue workers

Basically, every task is executed synchronously. But under certain circumstances, you don't want to block user requests until time-consuming tasks have finished. If you are considering to run a setup with thousands of cards and users, you can enable asynchronous processing using the Q_CLUSTER setting in production.py.dist. After that, start the cluster workers using the following command: python manage.py qcluster [--settings memodrop.settings.production]

You should also read the official docs regarding Django Q.

Health check endpoint

The /admin/health/ route exposes a status endpoint which usually returns 200 OK if the application is healthy.



Setup the development environment:

python setup.py develop
pip install -e ".[dev]"

There are some fixtures for different scenarios:

python manage.py loaddata demo_users  # use demo credentials from categories/fixtures/demo_users.yaml
python manage.py loaddata demo_categories
python manage.py loaddata demo_share_contracts
python manage.py loaddata demo_cards


Feel free to write and run some unit tests after you've finished your work.

coverage run manage.py test .
coverage report


Commit and tag your work (following the Semantic Versioning 2.0.0 guidelines):

bumpversion patch  # use major, minor or patch
git push origin master --tags