A list of password hashers, on successful login the user is upgraded to the top password hasher. Makes it very simple to switch to a new scheme or work factor.
Outside Django, if you're using Python, there's no excuse to not use passlib[0] whose cryptcontext object[1] handles this situation fantastically: create a cryptcontext with all the hash types you accept as input, and put any "old" hash in the `deprecated` list (or just set `deprecated=['auto']` in 1.6, it'll deprecate any non-default hash — the default hash is the first of the list, or the one passed as the `default` parameter). Then you can just use the relevant method to know that the authentication was successful and you should update the in-db hash:
hash = CryptContext(
# upgrading from an md5_crypted system
["sha256_crypt", "md5_crypt"],
deprecated=['auto'])
# in auth code
valid, updated = hash.verify_and_update(password, current_hash)
if not valid:
# error out
if updated is not None:
# updated is the new hash to set in database