I'm a core maintainer of Django-Tastypie, the oldest REST framework for Django. It predates Django-Rest-Framework and comes from the very earliest days of Class-Based Views, from when they were still very controversial. It's still in use by a lot of developers and companies, though these days the primary development efforts are in keeping it up-to-date with Django releases and bugfixing. It's still in Beta for some legacy reasons, but it's exceptionally mature.

This isn't about DRF vs Tastypie; they both have their advantages and disadvantages. If you're trying to decide on a REST framework, my first suggestion is the same one I'd give for trying to find the right library for any project: figure out your needs, your team's needs, pare your options down to a few viable ones, and then try building something with all of them. Don't take any developer's word for which is best; we all (myself included) have biases grown from out own projects and experiences and those are not your projects or experience.

Instead, this post is about something I do about once or two a year: releasing a new version of a (relatively) popular project via PyPI and Github.

Because release management is not part of my day job and because I only do it once or twice a year, I always get something wrong.

  1. Version everything

Don't put your version number in setup.py. Thankfully the project did this already when I inherited it: https://github.com/django-tastypie/django-tastypie/blob/master/setup.py#L11 Keep one centralized version number, then import it into setup.py and use it in setup().

But setup.py is almost certainly not the only reference to the current version. Here's everywhere we need to bump the version number:

  • README - used by GitHub to show our project description at the top-level project page.
  • Documentation - and specifically our index.rst page. Our docs are automatically built and deployed to Read The Docs which saves us a lot of work.
  • Release notes - these are included in the docs, and every new release gets a new notes file, which must also be linked from the release_notes/index.rst page. More on that below.
  1. Release Notes

Tracking everything that has changed since the last release is a difficult but necessary step. In a perfect world, you'd be tracking changes as they are made, but this is hard enough for a single-developer project much less a community-maintained project. Instead, GitHub provides some tools for this on the Releases page. By default, this page shows the last release and, crucially, a link to show all commits made to master since this release. I try to keep this to the broad strokes, keeping the nitty-gritty details confined to our Backwards-Incompatible Changes file.

"Releasing" a Python library on GitHub is a bit of an anachromism; most users will be deploying from PyPI. But it is a simple process (just create a new Draft Release from the Releases page, pointing at either master or a release tag.) and worth it for the rollup diffs and commit log alone.

  1. Release to PyPI

Make sure everything is ready to go before this step. It's not possible to change a release once published to PyPI.

Every time I do this, the toolchain has changed. Most recently, the preferred tool has changed to Twine which was relatively painless (if arcane):

$ pip install twine
$ python setup.py sdist
$ twine upload dist/*

You can provide authentication for twine in a configuration file, but given the recent NPM credential debacle it is probably a good idea to avoid putting your PyPI password in any cleartext file.


Detecting Incomplete or Missing Migrations with Django and CircleCI

Tue 04 October 2016 by George Dorn

Update (2017-06-15): Django 1.10 added --check and deprecated --exit. This makes the logic far more easy to follow. Just run this instead:

python manage.py makemigration --dry-run --no-input --check

And the same command will work in CircleCI (or your favorite CI service.)

Original, deprecated:

It's pretty easy to put …

read more

Auto Screenshot Selenium Test Failures (In Django)

Thu 22 September 2016 by George Dorn

These days, every codebase I work on runs tests under some form of third-party continuous integration. This is great, because people are lazy and don't always run all of their tests before pushing. But it's not so great when trying to debug why a test failed on the CI server …

read more

Multitouch on newer Elantech Touchpads in Linux

Sun 23 June 2013 by George Dorn

I'm running Linux Mint 14 XFCE on a Gigabyte U2442. The touchpad ends up recognized as a PS2 mouse and therefore lacks touchpad features. Several symptoms:

"Couldn't find synaptics properties. No synaptics driver loaded?" when running synclient.

The device showing up as "PS/2 Generic Mouse" when running xinput list …

read more

Using Tastypie Inside Django

Wed 21 November 2012 by George Dorn

Make use of a Tastypie's API from within Django

Tastypie is an excellent way to generate a REST API with minimal coding. But often it exists as a separate means of accessing your data, with its own implementation of your business logic, while your views also implement business logic.

If …

read more

Legacy BooleanField in Django

Mon 29 November 2010 by George Dorn

A legacy BooleanField supporting all kinds of antiquated ways of storing boolean values.

Django's inspectdb is pretty good at providing models that will at least read and write from your legacy database. But to get real power out of the ORM, you may need to provide some custom mapping for …

read more

Using Django Auth with a legacy app

Tue 09 November 2010 by George Dorn

One strategy for integrating a legacy python application with Django.

At work, we're planning to switch to Django. Rather than doing a complete feature freeze for six months while we rewrite the site in Django, the decision has been made to run two codebases and migrate features to Django slowly …

read more

Django vs SQAlchemy (vs PyDO) Speed Tests

Fri 29 October 2010 by George Dorn

Speed tests for SQLAlchemy vs Django vs PyDO

At work, we're preparing to move away from a 6-year-old homebrew web framework to Django. In the process, I figured I'd do some speed tests of the old ORM (PyDO, version one, last updated in 2004 and with an author's contact email …

read more

Hygienic unit testing with Solr.

Mon 13 September 2010 by George Dorn

Python unittest hygiene and Solr.

A sane methodology for testing an application that uses a database looks like this:

  1. Prop up an empty database, preferably using the same engine as production.
  2. Import some fixture data to play with (optional).
  3. Run tests that manipulate data in this database.
  4. Roll back the …
read more

The State of WSGI and character encoding.

Tue 03 August 2010 by George Dorn

Imagine you've inherited a legacy codebase with urls that look like this:

http://host.com/music/{band_name}
http://host.com/music/{band_name}/{album_name}

Now imagine that you have over a million unique bands in your database, in dozens of languages with all sorts of weird punctuation. Ignoring the special case …

read more