[bitbake-devel] [PATCH 06/19] toaster: toaster table add raw data

Alex DAMIAN alexandru.damian at intel.com
Wed Jun 10 14:38:54 UTC 2015


From: Alexandru DAMIAN <alexandru.damian at intel.com>

We add in a JSON response both the raw data and the rendered
version for display. The rendered fields start with "static:"
to mark a different "namespace".

The toaster.js is updated to always display the "static:" version
of a field, if it exists (and ignore the raw data unless the
static rendering is missing).

Signed-off-by: Alexandru DAMIAN <alexandru.damian at intel.com>
---
 lib/toaster/toastergui/static/js/table.js | 14 +++++++++++++-
 lib/toaster/toastergui/views.py           | 31 ++++++++++++++++++++++++++++++-
 lib/toaster/toastergui/widgets.py         | 16 +++++++++++-----
 3 files changed, 54 insertions(+), 7 deletions(-)

diff --git a/lib/toaster/toastergui/static/js/table.js b/lib/toaster/toastergui/static/js/table.js
index 7588a4a..80e9ec2 100644
--- a/lib/toaster/toastergui/static/js/table.js
+++ b/lib/toaster/toastergui/static/js/table.js
@@ -113,8 +113,20 @@ function tableInit(ctx){
     for (var i in tableData.rows){
       var row = $("<tr></tr>");
       for (var key_j in tableData.rows[i]){
+        /* if we have a static: version of a key, prefer the static: version for rendering */
+        var orig_key_j = key_j;
+
+        if (key_j.indexOf("static:") === 0) {
+          if (key_j.substr("static:".length) in tableData.rows[i]) {
+            continue;
+          }
+          orig_key_j = key_j.substr("static:".length)
+        } else if (("static:" + key_j) in tableData.rows[i]) {
+          key_j = "static:" + key_j;
+        }
+
         var td = $("<td></td>");
-        td.prop("class", key_j);
+        td.prop("class", orig_key_j);
         if (tableData.rows[i][key_j]){
           td.html(tableData.rows[i][key_j]);
         }
diff --git a/lib/toaster/toastergui/views.py b/lib/toaster/toastergui/views.py
index 91c4fa2..280159a 100755
--- a/lib/toaster/toastergui/views.py
+++ b/lib/toaster/toastergui/views.py
@@ -87,6 +87,35 @@ def _project_recent_build_list(prj):
             list(prj.buildrequest_set.filter(state__in=[BuildRequest.REQ_COMPLETED, BuildRequest.REQ_FAILED]).order_by("-pk")[:3]))
 
 
+
+def objtojson(obj):
+    from django.db.models.query import QuerySet
+    from django.db.models import Model, IntegerField
+    from django.db.models.fields.related import ForeignKey
+
+    if isinstance(obj, datetime):
+        return obj.isoformat()
+    elif isinstance(obj, timedelta):
+        return obj.total_seconds()
+    elif isinstance(obj, QuerySet) or isinstance(obj, set):
+        return list(obj)
+    elif type(obj).__name__ == "RelatedManager":
+        return [x.pk for x in obj.all()]
+    elif hasattr( obj, '__dict__') and isinstance(obj, Model):
+        d = obj.__dict__
+        nd = dict(d)
+        for di in d.keys():
+            if di.startswith("_"):
+                del nd[di]
+            elif isinstance(d[di], Model):
+                nd[di] = d[di].pk
+            elif isinstance(d[di], int) and hasattr(obj, "get_%s_display" % di):
+                nd[di] = getattr(obj, "get_%s_display" % di)()
+        return nd
+    else:
+        raise TypeError("Unserializable object %s (%s) of type %s" % ( obj, dir(obj), type(obj)))
+
+
 def _template_renderer(template):
     def func_wrapper(view):
         def returned_wrapper(request, *args, **kwargs):
@@ -127,7 +156,7 @@ def _template_renderer(template):
                     else:
                         raise TypeError("Unserializable object %s of type %s" % ( obj, type(obj)))
 
-                return HttpResponse(jsonfilter(context, default=_objtojson ),
+                return HttpResponse(jsonfilter(context, default=objtojson ),
                             content_type = "application/json; charset=utf-8")
             else:
                 return render(request, template, context)
diff --git a/lib/toaster/toastergui/widgets.py b/lib/toaster/toastergui/widgets.py
index 4347a3f..82b7514 100644
--- a/lib/toaster/toastergui/widgets.py
+++ b/lib/toaster/toastergui/widgets.py
@@ -37,6 +37,7 @@ import json
 import collections
 import operator
 
+from toastergui.views import objtojson
 
 class ToasterTable(TemplateView):
     def __init__(self, *args, **kwargs):
@@ -275,19 +276,25 @@ class ToasterTable(TemplateView):
 
                 for col in self.columns:
                     field = col['field_name']
+                    if not field:
+                        field = col['static_data_name']
+                    if not field:
+                        raise Exception("Must supply a field_name or static_data_name for column %s.%s" % (self.__class__.__name__,col))
                     # Check if we need to process some static data
                     if "static_data_name" in col and col['static_data_name']:
-                        required_data[col['static_data_name']] = self.render_static_data(col['static_data_template'], row)
+                        required_data["static:%s" % col['static_data_name']] = self.render_static_data(col['static_data_template'], row)
 
                         # Overwrite the field_name with static_data_name
                         # so that this can be used as the html class name
 
                         col['field_name'] = col['static_data_name']
-                    else:
+
+                    if True:        # we add the raw model data at all times
                         model_data = row
                         # Traverse to any foriegn key in the object hierachy
                         for subfield in field.split("__"):
-                            model_data = getattr(model_data, subfield)
+                            if hasattr(model_data, subfield):
+                                model_data = getattr(model_data, subfield)
                         # The field could be a function on the model so check
                         # If it is then call it
                         if isinstance(model_data, types.MethodType):
@@ -299,8 +306,7 @@ class ToasterTable(TemplateView):
 
         except FieldError:
             print "Error: Requested field does not exist"
-
-        data = json.dumps(data, indent=2, cls=DjangoJSONEncoder)
+        data = json.dumps(data, indent=2, default=objtojson)
         cache.set(cache_name, data, 60*30)
 
         return data
-- 
1.9.1




More information about the bitbake-devel mailing list