RESTFul Direct Certificate Discovery

Direct is a health information exchange framework based on Public Key Infrastructure (PKI) and email. Public x509 certificates must be discoverable for Direct to work properly. Currently Direct uses both DNS and LDAP for this purpose. This blog post outlines a proposal for a new RESTful method of Direct certificate discovery.

The Direct Applicability statement already provides two methods to discover certificates: DNS, and LDAP. Since DNS and LDAP are easy enough to query, why do we need a third method? In a word, simplicity. If the use of a technology is going to be mandated by the government, as in the case of Direct via Meaningful Use, shouldn’t it be simple, inexpensive, and as friction-less as possible? We’re living in a web world so why not leverage this commodity. I’ll be the first to admit that it can be hard to reduce complexity by adding requirements. We should only add requirements if they are needed. I’d like outline some of the issues with the DNS and LDAP approaches.

Issues Serving Direct Certificates via DNS and LDAP

1. DNS does not work on many large networks. On many networks including Comcast, Time Warner, and others, looking up a Direct certificate via DNS is not possible because these networks do not allow large DNS lookups. The certificates are too large and are blocked on these networks.

2. No large hosting provider (including Amazon, GoDaddy, Yahoo, DreamHost, Google, and others) provide support for certificate “CERT-type” records. Hosting your own DNS server is complicated and burdensome. Most organizations leave this to their hosting provider, however, if you want to serve certificates for Direct via DNS you have no choice but to host your own DNS server or contract out to a third party service.

3. Some security-minded people may frown on the idea of anonymous access to an LDAP server, especially if it also contains other resources with restricted access. In addition, LDAP is also and burdensome to setup under the Linux/Unix.

The first item in the list is going to cause a lot of problems. See this for yourself using the command-line tool “dig”. (You could also use “nslookup”). Try typing the following:

> dig CERT

Depending on your network, you may or may not get a response. For example, on Time Warner or Comcast you might get this instead of the certificate.

;; Truncated, retrying in TCP mode.

; <<>> DiG 9.8.1-P1 <<>> CERT
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 3004
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0


;; Query time: 1 msec
;; WHEN: Thu Aug 22 13:45:31 2013
;; MSG SIZE  rcvd: 43

If you try the same command on another network (from an Amazon EC2 instance for example), you will get the certificate. DNS is working as expected but our network is blocking it. Since many providers throughout the United States use Time Warner, Comcast, and others as Internet Service Providers (ISPs), this presents a problem. If an organization wants to host Direct and lookup certificates via DNS, then their network could not.

It may require someone, such as the US government, to require all major ISPs to change their network configuration to support Direct (i.e. large DNS responses).

I assume that is possible and has already happened in many cases, but as I said before its a web world. There’s got to be a better way! Below is my proposal for serving Direct certificates in a simple RESTFul fashion. I call it RCD for “RESTFul Certificate Discovery”. Here are the details.

RESTFul Certificate Discovery

RCD Syntax


                              |-- Email or Domain part --|

RCD Protocol Specification

RCD works by ensuring the URL is predictable. The RCD service MUST operate on a sub-domain named “rcd” on “your-domain”. The “your-domain” in the email/domain part MUST match in the email part. This ensures the system remains distributed among organizations just like DNS. The RCD service ALWAYS returns the public certificate in “.pem” (Privacy Enhanced Mail) format and ALWAYS with an HTTP status code of 200. If the certificate is not found or does not exist then RCD response SHALL ALWAYS return some HTTP response code other than 200 (e.g. 404, 4xx, 5xx). RCD SHALL ALWAYS operate over HTTP on port 80 or port 443 for HTTPS. A RCD client MUST ALWAYS check the HTTPS URL first and then the corresponding HTTP URL. How certificates get into RCD is explicitly left undefined and is left to the implementer.

RCD Example:

RCD is just an HTTP GET request to the URL “”

Here is another domain-bound example.

The RCD service responds with the .pem formatted certificate file or a non-200 HTTP status (404, 400 etc.).

That’s it. That’s the entire specification. New approaches like RCD are specifically allowed in the current Direct spec:”Direct Project solutions MAY obtain digital certificates through some other out-of-band and thus manual means”.

Discover a Certificate via RCD

What’s this look like in action?. We will use a web client called “wget” that is already installed on Mac and most Linux flavors. You could also use a web browser, curl, or any number of web clients.

> wget
> cat
...removed for brevity...

We use “wget” to fetch the certificate at the predictable URL. Then we use “cat” to display the contents of the file that was downloaded.

Hosting RCD

So we see how simple RCD is to query, but what about hosting? This is really the best part to this approach – it really couldn’t be easier. Here’s why:

1.RCD can be implemented with just about any web server (Apache, Microsoft IIS, NGINX, etc).

2. RCD is simple enough to be implemented within a content delivery network (CDN) such as Amazon S3 or Rackspace Cloud Files. Take Amazon S3 for example. S3 Storage is inexpensive and redundant. What this means is that even a fairly hefty deployment would likely only run pennies a month or few dollars per year. Setup is simple because all you need to do is place your files in a sub-directory called “read” and you’re done. No code is necessary to implement this protocol. Its just a static file at a predictable URL.

3.RCD does not break on some networks as described above in “Issues serving Direct certificates via DNS and LDAP”.

Technical Note:To make RCD work with S3, you need to setup a “vanity URL” on the S3 bucket and create a CNAME within your DNS provider’s (e.g. GoDaddy, Yahoo, etc.) configuration. You will need the authority to make changes to DNS for the domain .

Drawbacks, Conclusions, and Next Steps

The key drawback to this approach is that it requires existing Direct implementations to add the functionality to query for certificates in this way. I’d estimate this would require about 50 lines of code in Java and would be very straightforward. Another drawback is that there isn’t a standard RFC to point to when it comes to REST/RESTFul approaches. That being said RESTful approaches are usually much easier to use and this is why they have largely supplanted more complicated SOAP services.

In my humble opinion, the juice is worth the squeeze. RCD will result in a solution that is orders of magnitude simpler and more cost effective than current options. I am writing this blog post as an open letter to the Direct community hoping that this approach will receive consideration. Thoughts? Opinions? Suggestions?



How to Serve Public Certificates with BIND for the Direct Project

Serving public certificates via DNS is quite an obscure endeavor. This is made quite evident by the total lack of documentation on how to serve CERT type records using BIND.The Direct Project requires that public certificates are discoverable via DNS and LDAP. BIND is by far the most widely used nameserver on the Internet and so this article describes how to get BIND to serve certificates for a Direct implementation.

Adding the certificate to BIND’s zone file is the tricky bit. You must do two things to the certificate so that BIND will serve it correctly. 1.) Calculate the “key tag” and 2.) format the public key correctly. It is not just the contents of a .pem file. The the certs’s zone file entry must be all on one line.

To make this task easier we have created a free open-source command line utility called “BIND Certificate Converter” or just “bcc” for short. bcc accepts two command line parameters; 1.) a host name and 2.) a certificate file (in .pem format). bcc outputs a suitable BIND zone file entry. You can redirect the output of this utility to append to your zone file. We will illustrate this with an example bewlow. In this example, we assume you are using BIND 9 on Ubuntu. The utility BIND Certificate Converter “bcc” also requires that dnspython and openssl are installed. Let start by making sure we have everything we need installed.

sudo apt-get install python-dnspython openssl bind9

Copy the file “bcc” into “/usr/bin” and set it to executable. The source code is at the bottom of this blog entry.

sudo cp bcc /usr/bin
sudo chmod 755 /usr/bin/bcc

We have now installed BIND, bcc, and the other prerequisites. You will now have the directory /etc/bind. Lets change “cd” into that directory. The file we want to change for localhost is “/etc/bind/db.local”. We are assuming you have a file called “” sitting in your $HOME directory (/home/ubunutu/

Now we can give our utility bbc (source code below) a dry run before outputting anything.

bcc examplehost

Let’s make things easier and just switch to a root shell.

sudo su -

Now lets write the output of bcc to the end of “/etc/bind/db.local”

cd /etc/bind
bcc examplehost /home/ubuntu/ >> /etc/bind/db.local

Now we need to restart BIND for our change to take effect.

sudo /etc/init.d/bind9 restart

Now we can test it with “nslookup”. Execute the following command:

nslookup -type=CERT myexamplehost.localhost localhost

The BIND server responds:

Server:		localhost

myexamplehost.localhost	cert = PKIX 12437 RSASHA1 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzXVb5YJHmV7a ljGA2KHXPgJ3KmGkMCF9AIHOGsnNN1CuuN4gCRdPVhySVsyEjWLj2xby 6i7yc8Zau2AutrFEFBibXw1YQZvbzabxpG0zZV3tG88t+03OH2VJsK2t 5adxY8wufuY353NwiCMhLtsnRMMym9BbLqQWt3v1P+s9zqq1bLQYQYJC ZexUVhBnjEEVL5oschErtoahpRlmhE1LxtmxKr75mv8RfZV17Pbn7JbP Jk36wpFKpT9SGJWC27eqUFtorOOkH6Kr+j/fGs1GWKgXjMZpeADC14Yh KrDeJtpUL3zzUtsLN9nP/MbcCzHnwdRd4Sb+5V0K1S3R/vtrDQIDAQAB

It works (hopefully)! Here is the source code to bcc.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim: ai ts=4 sts=4 et sw=4
# Copyright 2013 Videntity
# Freely reuse under the terms of
# Last Updated: August 18 , 2013

# BIND Certificate Convert - Read in a host name and PEM certificate and write out the corresponding line of BIND's zone file.

import os, sys, hashlib
import subprocess
import dns.rdata
import dns.dnssec
import dns.rdataclass
import dns.rdatatype
import dns.rdtypes.ANY.DNSKEY

def find_between( s, first, last ):
        start = s.index( first ) + len( first )
        end = s.index( last, start )
        return s[start:end]
    except ValueError:
        return ""
def bind_cert_convert(hostname, pemcert):
    output,error = subprocess.Popen(["openssl", "x509", "-in",
                                      pemcert, "-pubkey","-noout",],
                             stderr= subprocess.PIPE
    clean_pk = find_between(output,
                            "-----BEGIN PUBLIC KEY-----",
                            "-----END PUBLIC KEY-----")
    clean_pk = clean_pk.replace("\n", "")
    decoded_clean_pk = clean_pk.decode('base64', strict)
    dnskey = dns.rdtypes.ANY.DNSKEY.DNSKEY(dns.rdataclass.IN,
                                           dns.rdatatype.DNSKEY, 0, 0,
    bind_entry = "%s\tIN\tCERT\tPKIX %s RSASHA1 %s" % (hostname,
    print bind_entry
if __name__ == "__main__":
    if len(sys.argv)!=3:
        print "Usage: [HOST_NAME] [PEM_CERT_FILENAME]"
    bind_cert_convert(sys.argv[1], sys.argv[2])

So now there is documentation! I’d like to give a special thank you to Bob Halley, author of the “dnspython” library for helping me figure this out.


Direct Certificate Authority –

Over the past few months Videntity has built a robust, fully-functional certificate authority designed specifically with the Direct Project in mind. (You can find the Direct Project wiki here). The original motivation behind building “The Direct Certificate Authority (CA)” or just “Direct CA” was facilitating Meaningful Use stage 2 testing and specifically health information systems’ compliance with the Direct Applicability Statement. One requirement in particular, testing revocation, required the use of an actual certificate authority that managed CRLs. It also turns out asking for a certificates to support Direct is a tall order with most CA’s because most are unfamiliar with the unique requirements and nuances of the Direct Project. Various CA’s often handle revocation differently, further complicating matters. The other freely available tool for building X509 certificates that will work with Direct is called “certGen”. certGen is a good tool, but lacks support for revocation (i.e. Certificate Revocation Lists (CRLs) and/or OSCP). Hence, Direct CA was born.

Direct CA is a web-based tool so there is no software to install. Its designed around the notion of “Trust Anchors” whereby a “Trust Anchor” acts like a miniature Certificate Authority. Subordinate (i.e child) email-address-bound and domain-bound certificates are created with the Trust Anchor as the parent. Direct CA also publishes all public certificates to the web automatically in common certificate formats (.pem and .der). Certificate Revocation Lists (CRLs) are generated and published on a per-trust-anchor basis get automatically updated every few hours.

Anyone may use Direct CA for free to create certificates for testing purposes. If interested, simply request an invitation code.. We hope this tool makes Direct development and implementation a little easier.

Here are answers to commonly asked questions.

Q: Can I use this software to manage my own organization’s certificate authority or HISP / Trust Anchor)?

A: Yes. Contact sales AT videntity dot com or complete the contact form for more information.

Q: Is Direct CA open source?

A: No. The service is free, but the source code is not public. Contact usfor more information on our shared source options.

Q: I see reference to a file x5c file. What’s that all about?

A: Unlike how certificates work within web browsers, with Direct the Applicability Statement has no requirement to check the certificate chain back to the root CA’s certificate. Direct only requires checking the chain back to the trust anchor. Its debatable on whether or not this is a security issue, but DirectC A creates and publishes the full chain in a convenient JSON format just in case you DO wish to check the validity of the entire chain. The “x5c” file is an “X509 certificate chain” file in JSON format. The format complies with the IETFdraft for JSON Web Key (JWK) for Public Key Infrastructure (X.509) (PKIX) Certificates. Thanks to Josh Mandel for suggesting basing this feature of the work by the Javascript Object Signing and Encryption (JOSE).

DISCLAIMER: Use of this tool by government organizations does not imply recommendation or endorsement. DirectCA is for testing purposes and is provided “as-is” without warranty.


Redirect to another URL in Django urls

Things have changed a bit in Django 1.5 with respect to how redirects work without writing a view. In Django 1.5, you must use “RedirectView”, but what may not be too obvious is that “reverse” does not work with “RedirectView”. You must to use “reverse_lazy” instead. I couldn’t find a complete example of this anywhere and hence it prompted me to write this post and answer this question on Stack Overflow. Hope this is helpful to someone.

Example using RedirectView and reverse_lazy:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim: ai ts=4 sts=4 et sw=4
# Copyright 2013 Videntity  
# Freely reuse under the terms of
# Last Updated: Aug 7 , 2013 

from django.conf.urls import patterns, include, url
from django.views.generic import RedirectView
from django.core.urlresolvers import reverse_lazy

# Uncomment the next two lines to enable the admin:
from django.contrib import admin


urlpatterns = patterns('',
    url(r'^$', 'home', name='website_home'),
    url(r'^redirect-home/$', RedirectView.as_view(url=reverse_lazy('website_home')), name='redirect_home'),


So in the above example, the url “/redirect-home” will redirect to “/”. Hope this helps.


ce – Certificate Examiner

This is a quick command-line utility for displaying information contained in an SSL certificates and CRLs. It is faster and easier to remember than the OpenSSL commands on which it is based. It allows you specify only a certificate’s filename. It guesses the certificate’s type based on the filename extension. This works with most pem, der, and p12 formatted files using common extension conventions.


> ce


        Version: 3 (0x2)
        Serial Number: 4861619212740627522 (0x4377f0ea809e8c42)
    Signature Algorithm: sha1WithRSAEncryption


OpenSSL is a prerequisite. Execute the following commands to ensure that “ce” is on your path and that it executes without invoking Python directly.

> sudo cp ce /usr/bin 
> sudo chmod 755 /usr/bin/ce

Source Code for ce

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim: ai ts=4 sts=4 et sw=4
# Copyright 2013 Videntity  
# Freely reuse under the terms of
# Last Updated: September 10 , 2013 

import os, sys
def certificate_explain(certfile):
    tmplower = certfile.lower()
    if tmplower.endswith("der"):
        certype = "der"
    elif tmplower.endswith("pem") or tmplower.endswith("crt"):
        certype = "pem"
    elif tmplower.endswith("p12") or tmplower.endswith("pfx"):
    elif tmplower.endswith("crl"):
       print "Unrecognized file extension.  The file must end in der, pem, crt, p12, pfx, or crl."
    if certype in ("pem", "der"):
        shellcmd = "openssl x509 -in %s -inform %s -noout -text" % (certfile,
    if certype == "p12":
        shellcmd = "openssl pkcs12 -info -in %s" % (certfile)
    if certype == "crl":
        shellcmd = "openssl crl -in %s -noout -text" % (certfile)
if __name__ == "__main__":
    if len(sys.argv)!=2:
        print "Usage: [CERT_FILENAME]"


A Command-line Utility & Library to Fetch Revoked Serial Numbers from a Certificate Revocation List (CRL)

This functionality is not available in openssl’s comand line utility, so I cooked this up to do the job. The library function returns a Python list and when used as a command-line utility it returns a JSON list. You will need to install pyOpenSSL. One way to do that is “pip install pyOpenSSL”.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim: ai ts=4 sts=4 et sw=4

import OpenSSL
import json, sys

def get_revoked_serials(path_to_crl):
    revoked_list = []
    with open(path_to_crl, 'r') as _crl_file:
        crl = "".join(_crl_file.readlines())
    crl_object = OpenSSL.crypto.load_crl(OpenSSL.crypto.FILETYPE_PEM, crl)
    revoked_objects = crl_object.get_revoked()
    for rvk in revoked_objects:
    return revoked_list

if __name__ == "__main__":
    if len(sys.argv)!=2:
        print "Usage: python [filepath]"
    rs = get_revoked_serials(sys.argv[1])
    print json.dumps(rs)

And here is how you use it.

    > python /opt/ca/crl/videntity-ca-crl.pem

TODO items:

  • Accept a URL or a local file path.
  • Accept an x509 certificate and follow the CRL distribution point URLs.

A Collection of Handy Django Authentication Backends

This blog entry desribes three Django Authenticaon backends you can use instead of the default “django.contrib.auth.backends.ModelBackend”. Below is a brief description of each.

EmailBackend – This allows the user to use wither his or her username or his or her email address to log in. Not you have to make sure that usernames and email addresses are unique across all users in order for this to work properly.

MobilePhoneBackend -This allows the user to login with his or her mobile phone number and password instead of using the user name. This assumes you have a UserProfile model defined with the field “mobile_phone_number”.

HTTPAuthBackend – A standard HTTP Auth backend. Use this for APIs. This one just username and password, but by using this method, it is easy to access you system like a web service.

Here is an example of using the HTTPAuth backend via curl.

curl -u "myuser:mypass" -X GET

Here is the file containing the Authentication Backends

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim: ai ts=4 sts=4 et sw=4

# A collection of handy authentication Backends. Copyright Videntity 2012.
# License: BSD

from django.contrib.auth.models import User
from django.core.validators import email_re
import binascii
from django.http import HttpResponse, HttpResponseRedirect
from django.contrib.auth.models import User, AnonymousUser
from django.contrib.auth.decorators import login_required
from django.template import loader
from django.contrib.auth import authenticate
from django.conf import settings
from django.core.urlresolvers import get_callable
from django.core.exceptions import ImproperlyConfigured
from django.shortcuts import render_to_response
from django.template import RequestContext
from models import UserProfile

class BasicBackend:
    def get_user(self, user_id):
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

class EmailBackend(BasicBackend):
    def authenticate(self, username=None, password=None):
        #If username is an email address, then try to pull it up
                user = User.objects.get(email=username)
            except User.DoesNotExist:
                return None
            #We have a non-email address username we should try username
                user = User.objects.get(username=username)
            except User.DoesNotExist:
                return None
        if user.check_password(password):
            return user
class MobilePhoneBackend(BasicBackend):
    def authenticate(self, username=None, password=None):
            up = UserProfile.objects.get(mobile_phone_number=username)
        except UserProfile.DoesNotExist:
            return None
        if up.user.check_password(password):
            return up.user
class HTTPAuthBackend(BasicBackend):
    def __init__(self, auth_func=authenticate, realm='API'):
        self.auth_func = auth_func
        self.realm = realm

    def is_authenticated(self, request):
        auth_string = request.META.get('HTTP_AUTHORIZATION', None)
        if not auth_string:
            return False
            (authmeth, auth) = auth_string.split(" ", 1)

            if not authmeth.lower() == 'basic':
                return False

            auth = auth.strip().decode('base64')
            (username, password) = auth.split(':', 1)
        except (ValueError, binascii.Error):
            return False
        request.user = self.auth_func(username=username, password=password) \
            or AnonymousUser()
        return not request.user in (False, None, AnonymousUser())
    def authenticate(self, request):
        auth_string = request.META.get('HTTP_AUTHORIZATION', None)

        if not auth_string:
            return AnonymousUser
            (authmeth, auth) = auth_string.split(" ", 1)

            if not authmeth.lower() == 'basic':
                return AnonymousUser

            auth = auth.strip().decode('base64')
            (username, password) = auth.split(':', 1)
        except (ValueError, binascii.Error):
            return AnonymousUser
        request.user = self.auth_func(username=username, password=password) \
            or AnonymousUser()
        return not request.user in (False, None, AnonymousUser())
    def challenge(self):
        resp = HttpResponse("Authorization Required")
        resp['WWW-Authenticate'] = 'Basic realm="%s"' % self.realm
        resp.status_code = 401
        return resp

    def __repr__(self):
        return u'<HTTPBasic: realm=%s>' % self.realm

How to Use the Backends in your Application

Define AUTHENTICATION_BACKENS in Note that I have commended out ModelBackend. This is because the EmailBackend checks both the user/password combination and the email/password combinations.

AUTHENTICATION_BACKENDS = (#'django.contrib.auth.backends.ModelBackend',

When attempting to use HTTPAuthBackend when using Apache/mod_wsgi, you’ll need to tell WSGI to pass the authorization to the Django application. You do this in a your Apache2 configuration file. On Ubuntu Linux this file might live at “/etc/apache2/sites-available/default”. In your virtualhost configuration for your Django application, you need to add the line “WSGIPassAuthorization On” right below the “WSGIScriptAlias” line.

Here is an example:

<VirtualHost *:80>
	ServerAdmin webmaster@localhost
	DocumentRoot /var/www
	<Directory />
		Options FollowSymLinks
                AllowOverride AuthConfig
	<Directory /var/www/>
		Options Indexes FollowSymLinks MultiViews
		AllowOverride None
		Order allow,deny
		allow from all
        WSGIScriptAlias / /home/ubuntu/django-apps/RESTCat/config/apache/django.wsgi
        WSGIPassAuthorization On
        Alias /static/admin/ /var/www/djadminstatic/
        Alias /static/ /home/ubuntu/django-apps/RESTCat/mainstatic/

	ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
	<Directory "/usr/lib/cgi-bin">
		AllowOverride None
		Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
		Order allow,deny
		Allow from all

	ErrorLog ${APACHE_LOG_DIR}/error.log

	# Possible values include: debug, info, notice, warn, error, crit,
	# alert, emerg.
	LogLevel warn

	CustomLog ${APACHE_LOG_DIR}/access.log combined

    Alias /doc/ "/usr/share/doc/"
    <Directory "/usr/share/doc/">
        Options Indexes MultiViews FollowSymLinks
        AllowOverride None
        Order deny,allow
        Deny from all
        Allow from ::1/128


Hope this helps someone.


How to Make Django Se Habla Español

This is a short how-to and checklist for getting Django to server
your app in another langauge. In this case, Spanish.

Modifications to Your Python Code

In views, forms, and models use ugettext_lazy on all strings that will be rendered to the user.

    from django.utils.translation import ugettext_lazy as _ 

Everywhere you have a string, yo need to add _:

#So this...
verbose_name = "This is a model label"
#becomes this...
verbose_name = _("This is a model label")

Modifications to Your Templates

In your templates load the i18n machinery

    {% load i18n %}

and then put all strings that you want to traslate in {% trans %} like so..

{% load i18n %}
{% trans "this is a string to translate"%} 
{% trans "this is another string"%} 

Management Commands in the Console

Now its time to build out the “po” files that can be given to the translator.
In your project’s home directory, create a directory to hold the translations:

mkdir locale

Now make files for spanish.

python makemessages -l es

This will create a file in “yourproject/locale/es/LC_MESSAGES/django.po”.

This is the text file that will contain the translation. The English string is the “key”, called the msgid. You must fill in the msgstr value in spanish for each string.

Now after the translation, you also need to compile to po file. You do this like so.

python compilemessages

Settings File

But wait! Thats not all. We need to make sure we have everything we need in the settings file.

Make sure all this is set in your settings file

USE_I18N = True

Add the middleware class for Locale (not sure this is actually documented)

    'django.middleware.locale.LocaleMiddleware',  #  <-- Add this line

Make sure Django knows where you placed your files.
I also did not find this in the documentation. A friend helped.

    # Always use forward slashes, even on Windows.
    # Don't forget to use absolute paths, not relative paths.
    os.path.join(BASE_DIR, 'locale'),

Now set your browser’s langauge to spanish “ES”. Now you should be muy bueno.


Calculating BMI in Python

If you ever need to calculate Body Mass Index (BMI) in Python, here’s how…

    def bmi_calc(height, weight):
        # height is in inches
        # weight is in pounds (lbs.)
        bmi=(float(weight) * 703) / (float(height) * float(height))
        bmi="%.1f" %(bmi)
        return bmi



Some HL7 IP will soon be Open Source

We at Videntity are glad to hear that most of the HL7 IP will soon be open source. We hope the spirit of data liberation continues in the health IT industry.