diff options
author | Alexandru DAMIAN <alexandru.damian@intel.com> | 2015-06-08 11:01:43 +0100 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2015-06-12 00:01:48 +0100 |
commit | 58600cf8e76f270969ded6ec63ac0908f39dae09 (patch) | |
tree | f87738a1ce5857a576c236f43b85b3ec83089c88 | |
parent | 4a2a057130e877eae96d726bc86c6b9f48ed1ca3 (diff) | |
download | poky-58600cf8e76f270969ded6ec63ac0908f39dae09.tar.gz |
bitbake: toaster: toaster table add raw data
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).
(Bitbake rev: 928ee3fd4b52ea14b7eb704f1f27351362a9d27a)
Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r-- | bitbake/lib/toaster/toastergui/static/js/table.js | 14 | ||||
-rwxr-xr-x | bitbake/lib/toaster/toastergui/views.py | 31 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/widgets.py | 16 |
3 files changed, 54 insertions, 7 deletions
diff --git a/bitbake/lib/toaster/toastergui/static/js/table.js b/bitbake/lib/toaster/toastergui/static/js/table.js index 7588a4ab9a..80e9ec2392 100644 --- a/bitbake/lib/toaster/toastergui/static/js/table.js +++ b/bitbake/lib/toaster/toastergui/static/js/table.js | |||
@@ -113,8 +113,20 @@ function tableInit(ctx){ | |||
113 | for (var i in tableData.rows){ | 113 | for (var i in tableData.rows){ |
114 | var row = $("<tr></tr>"); | 114 | var row = $("<tr></tr>"); |
115 | for (var key_j in tableData.rows[i]){ | 115 | for (var key_j in tableData.rows[i]){ |
116 | /* if we have a static: version of a key, prefer the static: version for rendering */ | ||
117 | var orig_key_j = key_j; | ||
118 | |||
119 | if (key_j.indexOf("static:") === 0) { | ||
120 | if (key_j.substr("static:".length) in tableData.rows[i]) { | ||
121 | continue; | ||
122 | } | ||
123 | orig_key_j = key_j.substr("static:".length) | ||
124 | } else if (("static:" + key_j) in tableData.rows[i]) { | ||
125 | key_j = "static:" + key_j; | ||
126 | } | ||
127 | |||
116 | var td = $("<td></td>"); | 128 | var td = $("<td></td>"); |
117 | td.prop("class", key_j); | 129 | td.prop("class", orig_key_j); |
118 | if (tableData.rows[i][key_j]){ | 130 | if (tableData.rows[i][key_j]){ |
119 | td.html(tableData.rows[i][key_j]); | 131 | td.html(tableData.rows[i][key_j]); |
120 | } | 132 | } |
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py index 91c4fa2543..280159ad2c 100755 --- a/bitbake/lib/toaster/toastergui/views.py +++ b/bitbake/lib/toaster/toastergui/views.py | |||
@@ -87,6 +87,35 @@ def _project_recent_build_list(prj): | |||
87 | list(prj.buildrequest_set.filter(state__in=[BuildRequest.REQ_COMPLETED, BuildRequest.REQ_FAILED]).order_by("-pk")[:3])) | 87 | list(prj.buildrequest_set.filter(state__in=[BuildRequest.REQ_COMPLETED, BuildRequest.REQ_FAILED]).order_by("-pk")[:3])) |
88 | 88 | ||
89 | 89 | ||
90 | |||
91 | def objtojson(obj): | ||
92 | from django.db.models.query import QuerySet | ||
93 | from django.db.models import Model, IntegerField | ||
94 | from django.db.models.fields.related import ForeignKey | ||
95 | |||
96 | if isinstance(obj, datetime): | ||
97 | return obj.isoformat() | ||
98 | elif isinstance(obj, timedelta): | ||
99 | return obj.total_seconds() | ||
100 | elif isinstance(obj, QuerySet) or isinstance(obj, set): | ||
101 | return list(obj) | ||
102 | elif type(obj).__name__ == "RelatedManager": | ||
103 | return [x.pk for x in obj.all()] | ||
104 | elif hasattr( obj, '__dict__') and isinstance(obj, Model): | ||
105 | d = obj.__dict__ | ||
106 | nd = dict(d) | ||
107 | for di in d.keys(): | ||
108 | if di.startswith("_"): | ||
109 | del nd[di] | ||
110 | elif isinstance(d[di], Model): | ||
111 | nd[di] = d[di].pk | ||
112 | elif isinstance(d[di], int) and hasattr(obj, "get_%s_display" % di): | ||
113 | nd[di] = getattr(obj, "get_%s_display" % di)() | ||
114 | return nd | ||
115 | else: | ||
116 | raise TypeError("Unserializable object %s (%s) of type %s" % ( obj, dir(obj), type(obj))) | ||
117 | |||
118 | |||
90 | def _template_renderer(template): | 119 | def _template_renderer(template): |
91 | def func_wrapper(view): | 120 | def func_wrapper(view): |
92 | def returned_wrapper(request, *args, **kwargs): | 121 | def returned_wrapper(request, *args, **kwargs): |
@@ -127,7 +156,7 @@ def _template_renderer(template): | |||
127 | else: | 156 | else: |
128 | raise TypeError("Unserializable object %s of type %s" % ( obj, type(obj))) | 157 | raise TypeError("Unserializable object %s of type %s" % ( obj, type(obj))) |
129 | 158 | ||
130 | return HttpResponse(jsonfilter(context, default=_objtojson ), | 159 | return HttpResponse(jsonfilter(context, default=objtojson ), |
131 | content_type = "application/json; charset=utf-8") | 160 | content_type = "application/json; charset=utf-8") |
132 | else: | 161 | else: |
133 | return render(request, template, context) | 162 | return render(request, template, context) |
diff --git a/bitbake/lib/toaster/toastergui/widgets.py b/bitbake/lib/toaster/toastergui/widgets.py index 4347a3f081..82b7514bd8 100644 --- a/bitbake/lib/toaster/toastergui/widgets.py +++ b/bitbake/lib/toaster/toastergui/widgets.py | |||
@@ -37,6 +37,7 @@ import json | |||
37 | import collections | 37 | import collections |
38 | import operator | 38 | import operator |
39 | 39 | ||
40 | from toastergui.views import objtojson | ||
40 | 41 | ||
41 | class ToasterTable(TemplateView): | 42 | class ToasterTable(TemplateView): |
42 | def __init__(self, *args, **kwargs): | 43 | def __init__(self, *args, **kwargs): |
@@ -275,19 +276,25 @@ class ToasterTable(TemplateView): | |||
275 | 276 | ||
276 | for col in self.columns: | 277 | for col in self.columns: |
277 | field = col['field_name'] | 278 | field = col['field_name'] |
279 | if not field: | ||
280 | field = col['static_data_name'] | ||
281 | if not field: | ||
282 | raise Exception("Must supply a field_name or static_data_name for column %s.%s" % (self.__class__.__name__,col)) | ||
278 | # Check if we need to process some static data | 283 | # Check if we need to process some static data |
279 | if "static_data_name" in col and col['static_data_name']: | 284 | if "static_data_name" in col and col['static_data_name']: |
280 | required_data[col['static_data_name']] = self.render_static_data(col['static_data_template'], row) | 285 | required_data["static:%s" % col['static_data_name']] = self.render_static_data(col['static_data_template'], row) |
281 | 286 | ||
282 | # Overwrite the field_name with static_data_name | 287 | # Overwrite the field_name with static_data_name |
283 | # so that this can be used as the html class name | 288 | # so that this can be used as the html class name |
284 | 289 | ||
285 | col['field_name'] = col['static_data_name'] | 290 | col['field_name'] = col['static_data_name'] |
286 | else: | 291 | |
292 | if True: # we add the raw model data at all times | ||
287 | model_data = row | 293 | model_data = row |
288 | # Traverse to any foriegn key in the object hierachy | 294 | # Traverse to any foriegn key in the object hierachy |
289 | for subfield in field.split("__"): | 295 | for subfield in field.split("__"): |
290 | model_data = getattr(model_data, subfield) | 296 | if hasattr(model_data, subfield): |
297 | model_data = getattr(model_data, subfield) | ||
291 | # The field could be a function on the model so check | 298 | # The field could be a function on the model so check |
292 | # If it is then call it | 299 | # If it is then call it |
293 | if isinstance(model_data, types.MethodType): | 300 | if isinstance(model_data, types.MethodType): |
@@ -299,8 +306,7 @@ class ToasterTable(TemplateView): | |||
299 | 306 | ||
300 | except FieldError: | 307 | except FieldError: |
301 | print "Error: Requested field does not exist" | 308 | print "Error: Requested field does not exist" |
302 | 309 | data = json.dumps(data, indent=2, default=objtojson) | |
303 | data = json.dumps(data, indent=2, cls=DjangoJSONEncoder) | ||
304 | cache.set(cache_name, data, 60*30) | 310 | cache.set(cache_name, data, 60*30) |
305 | 311 | ||
306 | return data | 312 | return data |