Accepting and spending bitcoins in a Django application

This tutorial shows how to use django-bitcoin to receive and send money in your Python + Django application. The walkthrough guides how to create a bitcoin wallet in your Django application, buy bitcoins, transfers bitcoins into your application and then spend them. This all is done interactively from the command, Django shell and Python prompt.The tutorial was tested on OSX. It should work on Linux unmodified. On Windows you are on your own.

django-bitcoin is a proven open source solution for handling bitcoins in your service. However, it might be rough on the edges, it is being actively developed and lacks satisfying documentation. If you need a helping hand to set it up please pop up on #localbitcoins-chat on or poke me by email.

The tutorial Django application code is available on Github. It was originally presented in PythonBrazil 2013. The tutorial code is MIT licensed and uses my personal fork of django-bitcoin. Disclaimer: I work with the related projects.

LocalBitcoins is hiring. LocalBitcoins is currently looking for fraud analyst, growth hacker, international support people and software developers.

1. Why accept bitcoin in your online service


In order to understand this tutorial, you need to have basic understanding of

  • Python 2.7
  • virtualenv
  • memcached
  • bitcoind
  • Django basics: how to configure Django project, MySQL, models, South migrations, using interactive Python shell.
  • How to consume piles of open source code from Github


Setup and configure memcached first.

Installation (virtualenv based):

git clone
cd django-bitcoin-example
virtualenv venv   # Create virtualenv folder caller venv
. venv/bin/activate  # Active virtualenv

Install Python dependencies using pip:

pip install -r requirements.txt

Tutorial walkthrough

django-bitcoin creates a so called bitcoin web wallet in your Django project.

  • You need to have a bitcoind installed on your desktop / server where you run the tutorial.
  • django-bitcoin reads transactions from bitcoind and duplicates them as Django data with convenient models to handle them in your application
  • django-bitcoin can send bitcoins from the system by calling bitcoind interfaces

2. Configuring bitcoind

Install bitcoind.

Note that the bitcoind installation takes hefty 10-20 GB disk space for the block chain data. Blockchain contains all transaction history of bitcoin ever. bitcoind downloads this data from the bitcoin network and it may take a while.

  • django-bitcoin communites with bitcoind over JSON-RPC protocol. You set the bitcoind address in
  • bitcoind transaction handling is done as polling, using Django management commands

Configure your bitcoind to accept connection with username and password.

Create file example/ and let’s put there in confidential settings (not stored on Github):


# How many bitcoin network confirmations are required until django-bitcoin considers the transaction
# as received

# Use Django signals to tell the system when new money has arrived to your wallets

3. Initializing database

django-bitcoin uses South for its schema management. Create a database (sqlite test.db file by default):

python syncdb
python migrate django_bitcoin

4. Do a test run

Let’s open the development web server and see that the Django admin is up with django-bitcoin:

python runserver_plus

Visit http://localhost:8000/admin to see the Django admin interface having addresses, wallets and such:

5. Creating a wallet

A wallet, django_bitcoin.models.Wallet, is a combination of receiving and sending bitcoin addresses and stores the bitcoin value associated with these addresses. A wallet can have infinite number of sending and receiving bitcoin addresses.

Bitcoin addresses can be created and used on demand. The sending and receiving addresses do not have relationship between them. When you receive bitcoins to your system they do not leave out from the same address. This is who most bitcoin web wallets behave.

Let’s start interactive IPython prompt:

python shell_plus

Then we create a wallet with an label. Usually if the application has only one wallet (not per user wallets) you call this wallet instance to master wallet:

master_wallet, created = Wallet.objects.get_or_create(label="master_wallet")

Then we need to have an receiving bitcoin address where this wallet can receive bitcoins and then print it out for us:

recv_address = master_wallet.receiving_address(fresh_addr=False)
print recv_address

Write down the bitcoin address you got as we are later sending bitcoins into it.

6. Purchase some test bitcoins

Go to and buy some bitcoins. is a person-to-person bitcoin exchange where you are not buying bitcoins from an organization, but from other users. This is easy and fast way to obtain your first bitcoins, as there is no cumbersome verification processes you need to undergo in centralized bitcoin exchanges. Think LocalBitcoins as eBay of bitcoins. provides different online payment methods. The recommended methods are:

  • Cash deposit (popular in US)
  • National bank transfer

If you are living a big city you can also try cash trade.

You can buy small amounts of bitcoins from me. I can also sell bitcoins on PayPal on a request.

7. Accepting incoming transaction

We have the receiving bitcoin address of our master wallet from before. Now we are going to send the bitcoins there from LocalBitcoins: you hit the Send on, the site submits the transaction to the bitcoin network. Bitcoin network consists of nodes which will confirm your transaction. After the certain transaction confirmation threshold is exceeded you can assume the transaction was safe and not double spent attempt. Usually this confirmation threshold is six confirmations, but you can set it lower if you want to have faster customer experience. It takes 5-30 minutes to process a transaction with six confirmations.

Now, in our own example application polls bitcoind which listens to bitcoin network. bitcoind exposes a bunch of commands over JSON-RPC protocol. You can call these commands even from the UNIX command line.

We have a Django management command for polling bitcoind. On each poll, we check the incoming transaction for receiving bitcoin addresses we have in our database. When the bitcoin network keeps confirming our transaction, the confirmation count of the transaction increases. When the threshold is exceeded, django-bitcoin writes down the transaction to the database as DepositTransaction and the amount of bitcoins in the wallet is increased.

For this example we run the polling command by hand. Usually this is a task delegated to Celery task scheduler:

python CheckTransactions

8. Checking the balance

CheckTransactions fires the Django signal handlers notifying the Django project for incoming transactions. For the simplicity, we do not use Django signalling in this example. Instead, we manually run CheckTransactions and after 20 minutes and see that the bitcoins have been received in our wallet:

python shell_plus
master_wallet = Wallet.objects.get(label="master_wallet")
print master_wallet.total_balance()

9. Spending the bitcoins

Now, we got the coins! Time to make some purchases. We go to an online shop selling high quality Brazilian music.

Then we’ll send the bitcoins from our wallet to buy this wonderful piece of art (the screenshot below is a mockup and not an actual store).

All bitcoin amounts are stored in Python decimal.Decimal instead of floats to avoid floating point rounding errors.

We fire up the Python shell again and send the bitcoins to the target address:

python shell_plus
from decimal import Decimal
master_wallet = Wallet.objects.get(label="master_wallet")
master_wallet.send_to_address("1Bk1Gwo6KVu2a85YkqHAPtdxmS8xHejDUB", Decimal("0.0505"), "Bought Michel Telo MP3")

Note that for every outgoing transaction there is a bitcoin network fee to compensate the bitcoin miners for confirming your transaction. The network fee is configured to be 0.0005 BTC in django_bitcoind by default. So the total amount to be send is the checkout price + network fee. Higher the paid network fee, faster the transaction is processed by bitcoin network.

10. Checking outgoing and past transactions

We can check the outgoing transactions from our wallet:

for t in WalletTransaction.objects.filter(from_wallet=master_wallet):
   print t, t.to_bitcoinaddress

If you enter the receiving address to you can see your transaction statuses in the bitcoin network. that’s it!

\"\" Subscribe to RSS feed Follow me on Twitter Follow me on Facebook Follow me Google+

This documentation was brought you by these awesome people

Sphinx is a software development documentation tool written in Python. It is used by hundreds of projects, of some of which you can find on

sphinxcontrib.contributors Sphinx extension adds a sidebar box showing the contributors of the documentation. This information is automatically sourced from Git commits and Github user profiles.

Often writing open source software documentation is a thankless task. Providing documentation is oversighted by many software developers. People who write documentation do not get to be in limelight like rockstar developers do. The sphinxcontrib.contributors Sphinx extension encourages writing documentation by giving the face time and link love for the writers on the documentation page itself by adding a new box to Sphinx sidebar.

1. Benefits

  • Give the credit where the credit is due
  • The process is automatic based on git history and there is no need to have separate contributors list
  • Show that the documentation is written by humans and it doesn’t born automatically
  • Encourage people to write more documentation

See the project on Github.

3. Installation

Install the package to your virtualenv:

pip install sphinxcontrib.contributors

Install templates and static media files needed for this extension to work. You can download the files from here. Use Github raw file view to download the file.

Add to your Sphinx static resource folder the following files:


Add to your Sphinx templates folder the following files:


4. Usage

The Sphinx HTML is fitted with information of Github API URL where to get commit for a specific file. Then a JavaScript AJAX request is used to pull the commit information. The authors are parsed from the commits.

You get a Github username as tooltip, Github profile link and Github avatar of each author.

  • If there is Github username available, then the Github gravatar or identifcon is displayed with a link to Github profile page
  • If the commiter was not a Github author, then the committer’s name is displayed on a blank image

5. Limitations

Currently the authors are resolved on the client-side using Github public API. This is suitable for low traffic documentation hosting.

  • Resolving authors during the documentation build time increases the build time considerably
  • With large documentation builds you might hit Github API throttling threshold, making it difficult to do continuous documentation builds

6. Source code and issue tracking

See the project on Github.

7. Other

The extension uses git command and Python sh library to extract the Git repository information. Transparency client-side semantic templating library is used to generate DOM tree for face links from Github API JSON.

This project was created in the Plone Conference 2013 with awesome people, many caipirinhas and a lot of fun.

\"\" Subscribe to RSS feed Follow me on Twitter Follow me on Facebook Follow me Google+

Plone: battle-scarred community with battle tanks

Here are my slides from Plone Conference 2013 presentation about Plone community, how I ended up as a Plone consultant and how I stopped doing it. The slides are not  content rich and a narrative is required for comprehension. I’ll put up a link to video recording when it becomes online.

The slide where exported with my pdf-to-html Python script, which converts PDF exported slides to a blog post HTML with <img alt> tags.

Remember: Plone is like Hotel California. You can checkout any time, but you can never leave.

Beauty of the beast Mikko Ohtamaa Plone Conference  2013 @moo9000

Agenda ! How Plone happens ! Why I started doing Plone ! Why I stopped doing Plone

Oldest living open source CMS* ! Zope 1998 ! Plone 2000 ! Plone Foundation 2004 *) unless claimed otherwise

Zope2/Startup/misc/ Copyright (C) 1999, 2000  Digital Creations, Inc. Guido van Rossum trying to learn Python

There is no one on the driverÕs seat The community is an organic mash up of small consulting shops  having beer* with public sector IT departments *) sometimes a caiprinha or two

2003 Nokia did user interface testing of Series 40 phones with Python scripting A nuclear blast proof phone Microsoft


Many many beers ago in galaxy far away Ploneconf 2007 - Napoli Having a PC

Everybody loves Plone

(except developers) ( ! ! )

Solving right problems wrong Python View Viewlet Manager Viewlets TAL HTML DOM / lxml Diazo XML XSLT Component LookupError WTF ??? Robot Git

Plone is not attractive ! Everybody who is not making money out of Plone doesnÕt want to touch it ! Ecosystem has found its niche , but it is not growing

! ItÕs hard to grow your business if Plone is core of your business ! I could work forever as a consultant alone, but meh By some bitcoins from me with reals!

There is unexplained beauty in Plone the community

Plone has only 1 feature ! There is no thing it cannot do  ! Most advanced plugin system ever written in any programming language ! Most advanced permission, role and sharing system which bends so you donÕt have to

Battle-scarred community ! Old enough to look into a mirror and admit the mistakes of the past ! Most friendly community ! No question goes unanswered ... but you might regret asking ÒWe were young.  We needed the money.Ó

Plone community attracts  most intelligent and interesting people...

...and happens everywhere Doing Plone logo at the swamp of a sunken city somewhere in Argentina

! Ugliest legacy codebase ! Not having smart enough living person to Þx your bug ! No one caring about us ...still... Even with...

Plone is the best CMS  for medium-large scale organizations with 15+ editors, several subsites and complex workßow needs

Plone rocks like no other community on this planet Open Source Hacker moo9000

\"\" Subscribe to RSS feed Follow me on Twitter Follow me on Facebook Follow me Google+