Page:  
Sep
3

The Problem with Using an HL7-based Format for Blue Button

I’d rather not compete with HL7, but the current state leaves me no choice but to speak up.

Yes it would be a step in the right direction if HL7’s IP was public. I have no issue with the idea of HL7 holding copyrights, charging for memberships, and voting rights. I just have an issue with its closed nature. W3C may be expensive but their standards are public and well adopted through industry. When HL7 adopts this model, I can perhaps embrace HL7 as a workable solution. Until then I’ll continue to beat the drum of using something else that is open source.

Hypothetically speaking if the ABBI content working group used CCDA as its format, then we would be forbidden by HL7 from actually putting the CCDA specification and the ABBI implementation guide out for public comment. In fact, some people within the ABBI working group may not even be able to review the work because they are not members of HL7 and thus forbidden to see the specification. Not a very transparent process.

Another issue with CCDA is the fact there are not complete XSDs (XML schemas) published by HL7. This makes its implementation subject to interpretation, which leads to interoperability problems. They do have a schema, but only a “top level”. The XSD should be exhaustive and it needs at a public URL so that there is one source of truth. This is how XML and XSD are supposed to work.

I’d make the point there is a big difference between an “open source implementation” and an “open source specification”. To paraphrase HTML inventor, Tim Berners Lee, “Regardless if you play your music on a million dollar pipe organ, or on a toddler’s xylophone, everyone should have the right to learn how to read the music and know what the notes mean.” If the meaning of music notes was a closed secret requiring membership, we would have a lot less music in the world wouldn’t you say? I’m all for the rights of businesses and individuals to develop proprietary software, open source software, or something in between. The specification for information interchange, however, should be open and transparent.

I’m not so sure the either XML or JSON is the right format, because neither meet the ABBI goal of human readability without some sort of software transformation. This makes things more complicated for the patient.

I’m thinking it should look a lot closer to the VA’s existing Blue Button format with some tweaks to make it easier to transform into a machine-friendly format. In this way we are still building off what is already done and we are maintaining the goal of human readability.

Aug
25

Get the Latest Object or a 404 in Django : get_latest_object_or_404

The get_object_or_404 is a handy Django shortcut. It keeps my views shorter.

In my case however, I had the need to get the latest object. In my situation I have surveys that can be asked more than one time to the same person. I want to fetch the most recent survey only.

get_object_or_404(Survey, patient_id=1234)  
#this could result in more than one object and may fail.

What I really want to do is soemthing like this:

get_object_or_404(Survey, patient_id=1234, latest=True)
#This does not work

..but alas Django doesn’t let me do that. A quick scan of the Django source code gave me a hint to build a custom function to handle my use case. Below is my utility called “get_latest_object_or_404″, which always gets the latest object and thus ensures that I always only fetch one object and said object is the newest. This of course requires that you have latest defined in your model’s Meta class. So here goes.

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

from django.http import Http404
from django.shortcuts import _get_queryset

def get_latest_object_or_404(klass, *args, **kwargs):
    """
    Uses get().latest() to return object, or raises a Http404 exception if
    the object does not exist.

    klass may be a Model, Manager, or QuerySet object. All other passed
    arguments and keyword arguments are used in the get() query.

    Note: Like with get(), an MultipleObjectsReturned will be raised if more than one
    object is found.
    """
    queryset = _get_queryset(klass)
    try:
        return queryset.filter(*args, **kwargs).latest()
        
    except queryset.model.DoesNotExist:
        raise Http404('No %s matches the given query.' % queryset.model._meta.object_name)

I hope someone else finds this little contribution to the Django community useful. I think it should be added to the django.shortcuts library. Maybe I’ll propose that. Enjoy!

Jul
28

Fun with Framingham

Hot off the presses is an open source implementation of the Framingham 10 Year Heart Attack Risk Calculator. This software package consists of a command-line utility and a Python library for assessing the risk of a heart attack in individuals over the next 10 years. The variables used are sex, age, total cholesterol, HDL cholesterol, hypertension medication status, smoking status, and systolic blood pressure. For more information about the Framingham Heart Study click here. This software released under the Apache2 open source license.

Thanks to Ted Eytan (on Twitter @tedeytan) for pointing me to this in the first place.

You can get the full source code distribution and detailed usage instructions on Videntity’s GitHub Page.

You can install this package directly through pip by typing the following on your command line.

> sudo pip install python-framingham10yr

Now to use the function, you can do something like this.

>>> from framingham10yr.framingham10yr import framingham_10year_risk
>>> framingham_10year_risk("male", 36, 140, 80, 120, "no", "no")
{'status': 200, 'total_cholesterol': 140, 'smoker': False, 'blood_pressure_med_treatment': False, 'message': 'OK', 'sex': 'male', 'percent_risk': '<1%', 'age': 36, 'hdl_cholesterol': 80, 'systolic_blood_pressure': 120, 'points': -5}
>>> 

For your inspection and edification, below is implementation of the algorithm itself.

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

# Copyright Videnty Systems Inc, 2012 videntity.com
# Apache 2 License


import sys, json


GENDER_CHOICES = (('MALE', 'MALE'), 
                 ('FEMALE', 'FEMALE'),)

SMOKER_CHOICES = ((True, 'Yes'), 
                 (False, 'No'),)

def framingham_10year_risk(sex, age, total_cholesterol, hdl_cholesterol,
                           systolic_blood_pressure, smoker,
                           blood_pressure_med_treatment):
    """Requires:
        sex                             - "male" or "female" string
        age                             - string or int
        total_cholesterol               - sting or int 
        hdl_cholesterol                 - int
        systolic_blood_pressure         - int
        smoker                          - True or False. Also accepts 1 or 0 as
                                          a string or an int
        blood_pressure_med_treatment    - True or False. Also accepts 1 or 0
                                          as a string or an int
    """
    
    #be liberal in what we accept...massage the input
    if sex in ("MALE", "m", "M", "boy", "xy", "male", "Male"):
        sex = "male"
    if sex in ("FEMALE", "f", "F", "girl", "xx", "female", "Female"):
        sex = "female"    
    
    if smoker in ("yes", "Y", "y", "YES", "true", "t", "True", True, 1, "1"):
        smoker=True
    if smoker in ("no", "NO", "N", "n", "false", "f", "False", False, 0, "0"):
        smoker=False
    if  blood_pressure_med_treatment in ("yes", "Y", "y", "YES", "true", "t",
                                         "True", True, 1, "1"):
        blood_pressure_med_treatment = True
    if  blood_pressure_med_treatment  in ("no", "NO", "N", "n", "false", "f",
                                          "False", False, 0, "0"):
        blood_pressure_med_treatment = False

    #intialize some things -----------------------------------------------------
    errors = [] #a list of errors
    points = 0 
    age = int(age)
    total_cholesterol = int(total_cholesterol)
    hdl_cholesterol = int(hdl_cholesterol)
    systolic_blood_pressure = int(systolic_blood_pressure)
    
    try:
        blood_pressure_med_treatment = bool(int(blood_pressure_med_treatment))
    except(ValueError):
        errors.append("Blood pressure medication treatment must be set to True, False, 1, 0, yes, or no.")
    
    try:
        smoker = bool(int(smoker))
    except(ValueError):
        errors.append("Smoker must be set to True, False, 1, 0, yes, or no.")
        
    
    # Intitalize our response dictionary
    response = {"status": 200,
                "sex":sex,
                "message": "OK",
                "age": age,
                "total_cholesterol": total_cholesterol,  
                "hdl_cholesterol" : hdl_cholesterol,
                "systolic_blood_pressure": systolic_blood_pressure,
                "smoker": smoker,
                "blood_pressure_med_treatment": blood_pressure_med_treatment,
                }
    
    
    #run some sanity checks ----------------------------------------------------
    if not 20 <= age <=79:
        errors.append("Age must be within the range of 20 to 79.")
    
    if not 130 <= total_cholesterol <= 320:
        errors.append("Total cholesterol must be within the range of 130 to 320.")
    
    if not 20 <= hdl_cholesterol <= 100:
        errors.append("HDL cholesterol must be within the range of 20 to 100.")
    
    if not 90 <= systolic_blood_pressure<= 200:
        errors.append("Systolic blood pressure must be within the range of 90 to 200.")
    
    if sex.lower() not in ('male', 'female'):
        errors.append("Sex must be male or female.")

    #Process males -----------------------------------------------------------
    if sex.lower()=="male":

        # Age - male        
        if  20 <= age <= 34:
            points-=9
        if  35 <= age <= 39:
            points-=4
        if  40 <= age <= 44:
            points-=0
        if  45 <= age <= 49:
            points+=3
        if  50 <= age <= 54:
            points+=6
        if  55 <= age <= 59:
            points+=8
        if  60 <= age <= 64:
            points+=10
        if  65 <= age <= 69:
            points+=12
        if  70 <= age <= 74:
            points+=14
        if  75 <= age <= 79:
            points+=16

        #Total cholesterol, mg/dL - Male ------------------------
        if  20 <= age <= 39:
            if total_cholesterol < 160:
                points +=0
            if 160 <= total_cholesterol <= 199:
                points+=4
            if 200 <= total_cholesterol <= 239:
                points+=7
            if 240 <= total_cholesterol <= 279:
                points+=9
            if total_cholesterol > 289:
                points+=11
        if  40 <= age <= 49:
            if total_cholesterol < 160:
                points +=0
            if 160 <= total_cholesterol <= 199:
                points+=3
            if 200 <= total_cholesterol <= 239:
                points+=5
            if 240 <= total_cholesterol <= 279:
                points+=6
            if total_cholesterol > 289:
                points+=8
        if  50 <= age <= 59:
            if total_cholesterol < 160:
                points +=0
            if 160 <= total_cholesterol <= 199:
                points+=2
            if 200 <= total_cholesterol <= 239:
                points+=3
            if 240 <= total_cholesterol <= 279:
                points+=4
            if total_cholesterol > 289:
                points+=5
        if  60 <= age <= 69:
            if total_cholesterol < 160:
                points +=0
            if 160 <= total_cholesterol <= 199:
                points+=1
            if 200 <= total_cholesterol <= 239:
                points+=1
            if 240 <= total_cholesterol <= 279:
                points+=2
            if total_cholesterol > 289:
                points+=3
        if  70 <= age <= 79:
            if total_cholesterol < 160:
                points +=0
            if 160 <= total_cholesterol <= 199:
                points+=0
            if 200 <= total_cholesterol <= 239:
                points+=0
            if 240 <= total_cholesterol <= 279:
                points+=1
            if total_cholesterol > 289:
                points+=1
        #smoking - male
        if smoker:
            if 20 <= age <= 39:
               points+=8 
            if 40 <= age <= 49:
               points+=5
            if 50 <= age <= 59:
               points+=3
            if 60 <= age <= 69:
               points+=1
            if 70 <= age <= 79:
               points+=1 
        else: # nonsmoker
            points += 0
         
        #hdl cholesterol
        if hdl_cholesterol > 60:
            points-=1
        if 50 <= hdl_cholesterol <= 59:
            points+=0
        if 40 <= hdl_cholesterol <= 49:
            points+=1
        if hdl_cholesterol < 40:
            points+=2
            
        #systolic blood pressure
        if not blood_pressure_med_treatment:
            if systolic_blood_pressure < 120:
                points+=0
            if 120 <= systolic_blood_pressure <= 129:
                points+=0
            if 130 <= systolic_blood_pressure <= 139:
                points+=1           
            if 140 <= systolic_blood_pressure <= 159:
                points+=1
            if systolic_blood_pressure >= 160:
                points +=2
        else: #if the patient is on blood pressure meds
            if systolic_blood_pressure < 120:
                points+=0
            if 120 <= systolic_blood_pressure <= 129:
                points+=1
            if 130 <= systolic_blood_pressure <= 139:
                points+=1           
            if 140 <= systolic_blood_pressure <= 159:
                points+=2
            if systolic_blood_pressure >= 160:
                points +=3
        
        #calulate % risk for males
        if points <= 0:
            percent_risk ="<1%"
        elif points == 1:
            percent_risk ="1%"
        
        elif points == 2:
            percent_risk ="1%"
            
        elif points == 3:
            percent_risk ="1%"
            
        elif points == 4:
            percent_risk ="1%"
            
        elif points == 5:
            percent_risk ="2%"
            
        elif points == 6:
            percent_risk ="2%"
            
        elif points == 7:
            percent_risk ="2%"
            
        elif points == 8:
            percent_risk ="2%"
            
        elif points == 9:
            percent_risk ="5%"
            
        elif points == 10:
            percent_risk ="6%"
            
        elif points == 11:
            percent_risk ="8%"
            
        elif points == 12:
            percent_risk ="10%"
            
        elif points == 13:
            percent_risk ="12%"

        elif points == 14:
            percent_risk ="16%"
            
        elif points == 15:
            percent_risk ="20%"
            
        elif points == 16:
            percent_risk ="25%"
            
        elif points >= 17:
            percent_risk =">30%"
            
    #process females ----------------------------------------------------------
    elif sex.lower()=="female":
        # Age - female        
        if  20 <= age <= 34:
            points-=7
        if  35 <= age <= 39:
            points-=3
        if  40 <= age <= 44:
            points-=0
        if  45 <= age <= 49:
            points+=3
        if  50 <= age <= 54:
            points+=6
        if  55 <= age <= 59:
            points+=8
        if  60 <= age <= 64:
            points+=10
        if  65 <= age <= 69:
            points+=12
        if  70 <= age <= 74:
            points+=14
        if  75 <= age <= 79:
            points+=16

        #Total cholesterol, mg/dL - Female ------------------------
        if  20 <= age <= 39:
            if total_cholesterol < 160:
                points +=0
            if 160 <= total_cholesterol <= 199:
                points+=4
            if 200 <= total_cholesterol <= 239:
                points+=8
            if 240 <= total_cholesterol <= 279:
                points+=11
            if total_cholesterol > 289:
                points+=13
        if  40 <= age <= 49:
            if total_cholesterol < 160:
                points +=0
            if 160 <= total_cholesterol <= 199:
                points+=3
            if 200 <= total_cholesterol <= 239:
                points+=6
            if 240 <= total_cholesterol <= 279:
                points+=8
            if total_cholesterol > 289:
                points+=10
        if  50 <= age <= 59:
            if total_cholesterol < 160:
                points +=0
            if 160 <= total_cholesterol <= 199:
                points+=2
            if 200 <= total_cholesterol <= 239:
                points+=4
            if 240 <= total_cholesterol <= 279:
                points+=5
            if total_cholesterol > 289:
                points+=7
        if  60 <= age <= 69:
            if total_cholesterol < 160:
                points +=0
            if 160 <= total_cholesterol <= 199:
                points+=1
            if 200 <= total_cholesterol <= 239:
                points+=2
            if 240 <= total_cholesterol <= 279:
                points+=3
            if total_cholesterol > 289:
                points+=4
        if  70 <= age <= 79:
            if total_cholesterol < 160:
                points +=0
            if 160 <= total_cholesterol <= 199:
                points+=1
            if 200 <= total_cholesterol <= 239:
                points+=1
            if 240 <= total_cholesterol <= 279:
                points+=2
            if total_cholesterol > 289:
                points+=2
        #smoking - female
        if smoker:
            if 20 <= age <= 39:
               points+=9 
            if 40 <= age <= 49:
               points+=7
            if 50 <= age <= 59:
               points+=4
            if 60 <= age <= 69:
               points+=2
            if 70 <= age <= 79:
               points+=1 
        else: #nonsmoker
            points += 0
         
        #hdl cholesterol - female
        if hdl_cholesterol > 60:
            points-=1
        if 50 <= hdl_cholesterol <= 59:
            points+=0
        if 40 <= hdl_cholesterol <= 49:
            points+=1
        if hdl_cholesterol < 40:
            points+=2
            
        #systolic blood pressure
        if not blood_pressure_med_treatment: #untreated
            if systolic_blood_pressure < 120:
                points+=0
            if 120 <= systolic_blood_pressure <= 129:
                points+=1
            if 130 <= systolic_blood_pressure <= 139:
                points+=2           
            if 140 <= systolic_blood_pressure <= 159:
                points+=3
            if systolic_blood_pressure >= 160:
                points +=4
        else: #if the patient is on blood pressure meds
            if systolic_blood_pressure < 120:
                points+=0
            if 120 <= systolic_blood_pressure <= 129:
                points+=3
            if 130 <= systolic_blood_pressure <= 139:
                points+=4           
            if 140 <= systolic_blood_pressure <= 159:
                points+=5
            if systolic_blood_pressure >= 160:
                points +=6
        
        #calulate % risk for females
        if points <= 9:
            percent_risk ="<1%"
        elif 9 <= points <= 12:
            percent_risk ="1%"
        
        elif 13 <= points <= 14:
            percent_risk ="2%"
            
        elif points == 15:
            percent_risk ="3%"
            

        elif points == 16:
            percent_risk ="4%"
            
        elif points == 17:
            percent_risk ="5%"
            
        elif points == 18:
            percent_risk ="6%"

        elif points == 19:
            percent_risk ="8%"
            
        elif points == 20:
            percent_risk ="11%"
            
        elif points == 21:
            percent_risk ="14%"
            
        elif points == 22:
            percent_risk ="17%"

        elif points == 23:
            percent_risk ="22%"
            
        elif points == 24:
            percent_risk ="27%"
            
        elif points >= 25:
            percent_risk ="30%"

    if errors:
        response['status']=422
        response['message'] = "The request contained errors and was unable to process."
        response['errors']=errors
    else:
        response['points']=points
        
        
        
        
        
        
        
        
        response['percent_risk']= percent_risk
    
    return response


if __name__ == "__main__":    
    """
    Accept values to calucluate the 10 years heart attack risk based on
    Framingham.
    """
    try: 
        sex=sys.argv[1].lower()
        age=sys.argv[2]
        total_cholesterol=sys.argv[3]
        hdl_cholesterol=sys.argv[4]
        systolic_blood_pressure=sys.argv[5]
        smoker=sys.argv[6].lower()
        blood_pressure_med_treatment=sys.argv[7].lower()
        
    except(IndexError):
        print "All values are required."
        print "Usage: framingham.py <sex> <age> <total_cholesterol> <hdl_cholesterol systolic_blood_pressure> <smoker> <blood_pressure_med_treatment>"
        print "Example: framingham.py male 25 152 56 130 0 0"
        exit(1)
        
    try:
        
        #execute the function
        result = framingham_10year_risk(sex, age, total_cholesterol,
                                       hdl_cholesterol, systolic_blood_pressure,
                                       smoker, blood_pressure_med_treatment)
        
        #return pretty-print json to standard out
        print json.dumps(result, indent=4)
          
    except():
        print "An unexpected error occured. Here is the post-mortem:"
        print sys.exc_info()
        
        

Jun
10

Less Bad is Mo’ Better – Thoughts on Last Week’s Health Code-a-Thon

Last weekend I participated in a code-a-thon sponsored by Health 2.0 and Kaiser Permanente. The goal was to develop applications that help fight obesity.

My team maters were Mark Scrimshire, Kerese Wright, and Simon Last. We developed a small application that provided “less bad” suggestions at fast food chains. For example, you might be going to McDonald’s and thinking about the Big Mac. Less Bad will let you know that the Big Mac has 593 calories and that better options might be the cheese burger with 313 calories or the hamburger with 265 calories. The application works in both a web browser or via SMS mobile text message interface.

Check out this screen shot

Less Bad Screen shot of a healthier option than the Big Mac

We took 3rd place and won $1,000. This was Mark’s brainchild and we plan to continue work on this application as time permits.

Jun
10

Useful Tip for Port Forwarding Apache (or other Web Server)

Problem

You are working on a remote web server where you do not have have access to view the web server’s content on port 80. In my case I only had SSH shell access over port 22.

Solution

Use SSH’s port forwarding capability to serve the content locally on localhost.

    sudo ssh -L 80:name_of_ip_of_webserver:80 username@name_or_ip_of_server_with_access_to_webserver
   

Then just provide the local root password and the password for username@name_or_ip_of_server_with_access_to_webserver. Make sure you stop Apache or other web server before doing this otherwise, this will fail because the port will not be able to bind to a port with an existing bound service. So you might need to do something like this.

    sudo apache2ctl stop
   

Now all you need to do is point your favorite web browser to: http://127.0.0.1/

May
8

How to get SASS going on Ubuntu 10.04

I found that “Ruby 1.8″, packaged with Ubuntu 10.04, does not seem to run SASS out of the box. This is my recipe, cobbled together from various websites, to get things going. I’m using Ruby Version Manager “rvm” to use an updated version of Ruby.

    sudo apt-get install curl git-core ruby
    bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer )
   

In ~/.bashrc change you need to replace the line that says:

   [ -z "$PS1" ] && return
   

with

   if [[ -n "$PS1" ]]; then
   

Then add this to the bottom:

    if [[ -s $HOME/.rvm/scripts/rvm ]] ; then source $HOME/.rvm/scripts/rvm ; fi
    fi   
   

Save. Then re-read the .bashrc file.

    source ~/.bashrc  
   

Then from the command line:

   rvm notes
   sudo apt-get install build-essential bison openssl libreadline5 libreadline-dev curl git-core zlib1g zlib1g-   dev libssl-dev vim libsqlite3-0 libsqlite3-dev sqlite3 libreadline-dev libxml2-dev git-core subversion autoconf
   rvm list known
   rvm install 1.9.2-head
    
   #Verify ruby is installed
   ruby -v
   

Now that we have ruby installed lets fetch compass.

    rvm 1.9.2-head
    gem install compass

Phew! Okay now we should be able to watch the SASS directory for changes.
Navigate to wherever your SASS lives and

    compass watch ./sass

Now compass and SASS should be working :-)

May
3

How to Delete a Remote Branch on Github

Sometimes git is hard. An example is deleting a remote branch. Its hard to understand and remember so that’s why this blogpost.

    git push origin :name_of_branch_to_delete
   

It literary means push nothing into branch “name_of_branch_to_delete” on origin (Github)”. Make sure to pay attention to the position of the colon.

Apr
30

Exploring DocNPI.com’s API

DocNPI is a website and webervice for searching information in the National Provider Index (NPI) Registry. The NPI Registry is maintained by HHS and is a registry of all physicians in the United States. The intersting part of DOCNPI for me is that it lets you fetch the information as JSON or CSV thus making it possible to query for this information and import it into other data sets as needed.
(more…)

Oct
14

Fetching Django’s Model’s ‘verbose_name’ and/or Form’s ‘label’ Attribute

Problem:

You want to display some information in a database record in Django, but you also want to display the field’s verbbose name.  In other words, you want to display “What is your favorite Color?” instead of the field name, “favorite_color” or the slightly better “Favorite Color”.  This can be a particular problem if you have very cryptic field names for some reason or another.

The problem is that in Django the “pretty label” information can be defined in the Model’s fields as “verbose_name” or possibly in a related Form as “label”.  In my case I was using ModelForms to make life easier. ModelForms, among other things, take the “verbose_name” values from your Models and stuff it into the Form’s fields “label” values.  You could just create a ModelForm based on your Model, and then fetch the label, but the Label is not defined in the Form if a verbose_name was not defined for the model.  This grabs the pretty label if it exists, and falls back to the field name if its undefined.  This problem is also discussed on Stack Overflow as:.

Django – Iterate over model instance field names and values in template

I’ve provided this solution there as well.

Solution:

There should really be a built-in way to do this. I wrote this utility build_pretty_data_view that takes a model object and form instance (a form based on your model) and returns a SortedDict.

Benefits to this solution include:

  • It preserves order using Django’s built-in SortedDict.
  • When tries to get the label/verbose_name, but falls back to the field name if one is not defined.
  • It will also optionally take an exclude() list of field names to exclude certain fields.
  • If your form class includes a Meta: exclude(), but you still want to return the values, then add those fields to the optional append() list.

To use this solution, first add this file/function somewhere, then import it into your views.py.

utils.py


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim: ai ts=4 sts=4 et sw=4
from django.utils.datastructures import SortedDict

def build_pretty_data_view(form_instance, model_object, exclude=(), append=()):
    i=0
    sd=SortedDict()

    for j in append:
        try:
            sdvalue={'label':j.capitalize(),
                     'fieldvalue':model_object.__getattribute__(j)}
            sd.insert(i, j, sdvalue)
            i+=1
        except(AttributeError):
            pass

    for k,v in form_instance.fields.items():
        sdvalue={'label':"", 'fieldvalue':""}
        if not exclude.__contains__(k):
            if v.label is not None:
                sdvalue = {'label':v.label,
                           'fieldvalue': model_object.__getattribute__(k)}
            else:
                sdvalue = {'label':k,
                           'fieldvalue': model_object.__getattribute__(k)}
            sd.insert(i, k, sdvalue)
            i+=1
    return sd

So now in your views.py you might do something like this

from django.shortcuts import render_to_response
from django.template import RequestContext
from utils import build_pretty_data_view
from models import Blog
from forms import BlogForm
.
.
def my_view(request):
   b=Blog.objects.get(pk=1)
   bf=BlogForm(instance=b)
   data=build_pretty_data_view(form_instance=bf, model_object=b,
                        exclude=('number_of_comments', 'number_of_likes'),
                        append=('user',))

   return render_to_response('my-template.html',
                          RequestContext(request,
                                         {'data':data,}))

Now in your my-template.html template you can iterate over the data like so…

{% for field,value in data.items %}

    <p>{{ field }} : {{value.label}}: {{value.fieldvalue}}</p>

{% endfor %}

Good Luck. Hope this helps someone!

Solution

Aug
19

OMHE Microsyntax for Medical Device Interoperability: An Open-Source Alternative to the Continua Alliance

OMHE (Open Mobile Health Exchange), pronounced “ooommm” is an open-source microsyntax for medical devices, mobile text messaging, Twitter®, smart phones, and any system capable of sending a short text string. OMHE’s goal is to provide device interoperability between systems that transmit or receive fitness and wellness information. Its designed for use by both humans and machines. Unlike XML or JSON its simple enough that in most cases a person can type or read OMHE. OMHE still has enough syntactical structure to be parsed and used by machines or software. Another key design decision in OMHE is that OMHE does not define the mode of transport, but simply the data itself. This means OMHE can be blurted out by an electronic weight scale or sent from a human via mobile text message.

OMHE was developed by group of health hackers interested in making it easier to create systems that communicate health information. As an open source specification, there is no license or club to join. Unlike the Continua Alliance which costs thousands to join and who’s utility is questionable, OMHE is a grassroots project defining a practical solution to interoperability. Those interested in contributing code, content, time or funding to the OMHE project should first request to join the Google Group at http://groups.google.com/group/omhe_microsyntax. The OMHE project is hosted on Google Code at http://code.google.com/p/omhe/.

Page: