Skip to content

Commit 47c9792

Browse files
committed
Added a very simple html version of the json API, to make it easier to explore the api manually.
- Legacy-Id: 9992
2 parents 24bc3a3 + 2fe8dcb commit 47c9792

21 files changed

Lines changed: 211 additions & 3 deletions

File tree

ietf/api/__init__.py

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
from django.conf import settings
66
from django.http import HttpResponse
77
from django.core.urlresolvers import reverse
8+
from django.utils.encoding import force_text
89

910
from tastypie.api import Api
10-
from tastypie.serializers import Serializer
11+
from tastypie.bundle import Bundle
12+
from tastypie.serializers import Serializer as BaseSerializer
1113
from tastypie.exceptions import BadRequest, ApiFieldError
1214
from tastypie.utils.mime import determine_format, build_content_type
1315
from tastypie.utils import is_valid_jsonp_callback_value
@@ -17,6 +19,58 @@
1719

1820
_api_list = []
1921

22+
class Serializer(BaseSerializer):
23+
def to_html(self, data, options=None):
24+
"""
25+
Reserved for future usage.
26+
27+
The desire is to provide HTML output of a resource, making an API
28+
available to a browser. This is on the TODO list but not currently
29+
implemented.
30+
"""
31+
from django.template.loader import render_to_string as render
32+
33+
options = options or {}
34+
35+
serialized = self.to_simple_html(data, options)
36+
return render("api/base.html", {"data": serialized})
37+
38+
def to_simple_html(self, data, options):
39+
"""
40+
"""
41+
from django.template.loader import render_to_string as render
42+
#
43+
if isinstance(data, (list, tuple)):
44+
return render("api/listitem.html", {"data": [self.to_simple_html(item, options) for item in data]})
45+
if isinstance(data, dict):
46+
return render("api/dictitem.html", {"data": dict((key, self.to_simple_html(val, options)) for (key, val) in data.items())})
47+
elif isinstance(data, Bundle):
48+
return render("api/dictitem.html", {"data":dict((key, self.to_simple_html(val, options)) for (key, val) in data.data.items())})
49+
elif hasattr(data, 'dehydrated_type'):
50+
debug.show('data')
51+
if getattr(data, 'dehydrated_type', None) == 'related' and data.is_m2m == False:
52+
return render("api/relitem.html", {"fk": data.fk_resource, "val": self.to_simple_html(data.value, options)})
53+
elif getattr(data, 'dehydrated_type', None) == 'related' and data.is_m2m == True:
54+
render("api/listitem.html", {"data": [self.to_simple_html(bundle, options) for bundle in data.m2m_bundles]})
55+
else:
56+
return self.to_simple_html(data.value, options)
57+
elif isinstance(data, datetime.datetime):
58+
return self.format_datetime(data)
59+
elif isinstance(data, datetime.date):
60+
return self.format_date(data)
61+
elif isinstance(data, datetime.time):
62+
return self.format_time(data)
63+
elif isinstance(data, bool):
64+
return data
65+
elif isinstance(data, (six.integer_types, float)):
66+
return data
67+
elif data is None:
68+
return None
69+
elif isinstance(data, basestring) and data.startswith("/api/v1/"): # XXX Will not work for Python 3
70+
return render("api/relitem.html", {"fk": data, "val": data.split('/')[-2]})
71+
else:
72+
return force_text(data)
73+
2074
for _app in settings.INSTALLED_APPS:
2175
_module_dict = globals()
2276
if '.' in _app:
@@ -119,4 +173,4 @@ def hydrate(self, bundle):
119173

120174
return value
121175

122-
176+

ietf/api/management/commands/makeresources.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class {{model.name}}Resource(ModelResource):{% if model.foreign_keys %}{% for fk
3232
{{fk.name|ljust:"16"}} = ToManyField({{fk.rmodel_name}}, '{{fk.name}}', null=True){% endfor %}{% endif %}
3333
class Meta:
3434
queryset = {{model.name}}.objects.all()
35+
serializer = api.Serializer()
3536
#resource_name = '{{model.resource_name}}'
3637
filtering = { {% for name in model.plain_names %}
3738
"{{ name }}": ALL,{%endfor%}{% for name in model.fk_names%}

ietf/api/templates/api/base.html

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<html>
2+
<head>
3+
<style type="text/css">
4+
p.comment {
5+
background-color: #cfc;
6+
border: solid black 1px;
7+
padding: 0.5em;
8+
}
9+
</style>
10+
</head>
11+
<body>
12+
<div id="page_wrapper">
13+
<p class="comment">
14+
This is a very simple html version of the JSON api, to make it easier to manually explore
15+
the API.<br/>
16+
To see the pure JSON version, add '?format=json' to the browser url, or access
17+
the API with the "Accept:" http header set to "Accept: application/json".
18+
</p>
19+
<section class="content">
20+
{% block content %}{{data}}{% endblock %}
21+
</section>
22+
</div>
23+
</body>
24+
</html>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
<!-- dictitem.html -->
3+
<div style="margin-left: 1em;">
4+
{% for key, value in data.items %}
5+
"{{key}}": {{value}}{% if not forloop.last %},{% endif %}<br/>
6+
{% endfor %}
7+
</div>
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[
2+
<!-- listitem.html -->
3+
<div style="margin-left: 1em;">
4+
{% for item in data %}
5+
{{item}}{% if not forloop.last %},{% endif %}
6+
{% endfor %}
7+
</div>
8+
]
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<!-- relitem.html -->
2+
<a href="{{fk}}">{{val}}</a>

ietf/community/resources.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class CommunityListResource(ModelResource):
1717
added_ids = ToManyField(DocumentResource, 'added_ids', null=True)
1818
class Meta:
1919
queryset = CommunityList.objects.all()
20+
serializer = api.Serializer()
2021
#resource_name = 'communitylist'
2122
filtering = {
2223
"id": ALL,
@@ -34,6 +35,7 @@ class ExpectedChangeResource(ModelResource):
3435
document = ToOneField(DocumentResource, 'document')
3536
class Meta:
3637
queryset = ExpectedChange.objects.all()
38+
serializer = api.Serializer()
3739
#resource_name = 'expectedchange'
3840
filtering = {
3941
"id": ALL,
@@ -47,6 +49,7 @@ class DisplayConfigurationResource(ModelResource):
4749
community_list = ToOneField(CommunityListResource, 'community_list')
4850
class Meta:
4951
queryset = DisplayConfiguration.objects.all()
52+
serializer = api.Serializer()
5053
#resource_name = 'displayconfiguration'
5154
filtering = {
5255
"id": ALL,
@@ -61,6 +64,7 @@ class ListNotificationResource(ModelResource):
6164
event = ToOneField(DocEventResource, 'event')
6265
class Meta:
6366
queryset = ListNotification.objects.all()
67+
serializer = api.Serializer()
6468
#resource_name = 'listnotification'
6569
filtering = {
6670
"id": ALL,
@@ -75,6 +79,7 @@ class RuleResource(ModelResource):
7579
cached_ids = ToManyField(DocumentResource, 'cached_ids', null=True)
7680
class Meta:
7781
queryset = Rule.objects.all()
82+
serializer = api.Serializer()
7883
#resource_name = 'rule'
7984
filtering = {
8085
"id": ALL,
@@ -90,6 +95,7 @@ class EmailSubscriptionResource(ModelResource):
9095
community_list = ToOneField(CommunityListResource, 'community_list')
9196
class Meta:
9297
queryset = EmailSubscription.objects.all()
98+
serializer = api.Serializer()
9399
#resource_name = 'emailsubscription'
94100
filtering = {
95101
"id": ALL,
@@ -104,6 +110,7 @@ class DocumentChangeDatesResource(ModelResource):
104110
document = ToOneField(DocumentResource, 'document')
105111
class Meta:
106112
queryset = DocumentChangeDates.objects.all()
113+
serializer = api.Serializer()
107114
#resource_name = 'documentchangedates'
108115
filtering = {
109116
"id": ALL,

ietf/dbtemplate/resources.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class DBTemplateResource(ModelResource):
1515
group = ToOneField(GroupResource, 'group', null=True)
1616
class Meta:
1717
queryset = DBTemplate.objects.all()
18+
serializer = api.Serializer()
1819
#resource_name = 'dbtemplate'
1920
filtering = {
2021
"id": ALL,

ietf/doc/resources.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class BallotTypeResource(ModelResource):
1414
positions = ToManyField(BallotPositionNameResource, 'positions', null=True)
1515
class Meta:
1616
queryset = BallotType.objects.all()
17+
serializer = api.Serializer()
1718
#resource_name = 'ballottype'
1819
filtering = {
1920
"id": ALL,
@@ -34,6 +35,7 @@ class DeletedEventResource(ModelResource):
3435
by = ToOneField(PersonResource, 'by')
3536
class Meta:
3637
queryset = DeletedEvent.objects.all()
38+
serializer = api.Serializer()
3739
#resource_name = 'deletedevent'
3840
filtering = {
3941
"id": ALL,
@@ -47,6 +49,7 @@ class Meta:
4749
class StateTypeResource(ModelResource):
4850
class Meta:
4951
queryset = StateType.objects.all()
52+
serializer = api.Serializer()
5053
#resource_name = 'statetype'
5154
filtering = {
5255
"slug": ALL,
@@ -59,6 +62,7 @@ class StateResource(ModelResource):
5962
next_states = ToManyField('ietf.doc.resources.StateResource', 'next_states', null=True)
6063
class Meta:
6164
queryset = State.objects.all()
65+
serializer = api.Serializer()
6266
#resource_name = 'state'
6367
filtering = {
6468
"id": ALL,
@@ -89,6 +93,7 @@ class DocumentResource(ModelResource):
8993
rfc = CharField(attribute='rfc_number', null=True)
9094
class Meta:
9195
queryset = Document.objects.all()
96+
serializer = api.Serializer()
9297
#resource_name = 'document'
9398
filtering = {
9499
"time": ALL,
@@ -122,6 +127,7 @@ class DocumentAuthorResource(ModelResource):
122127
author = ToOneField(EmailResource, 'author')
123128
class Meta:
124129
queryset = DocumentAuthor.objects.all()
130+
serializer = api.Serializer()
125131
#resource_name = 'documentauthor'
126132
filtering = {
127133
"id": ALL,
@@ -137,6 +143,7 @@ class DocEventResource(ModelResource):
137143
doc = ToOneField(DocumentResource, 'doc')
138144
class Meta:
139145
queryset = DocEvent.objects.all()
146+
serializer = api.Serializer()
140147
#resource_name = 'docevent'
141148
filtering = {
142149
"id": ALL,
@@ -157,6 +164,7 @@ class StateDocEventResource(ModelResource):
157164
state = ToOneField(StateResource, 'state', null=True)
158165
class Meta:
159166
queryset = StateDocEvent.objects.all()
167+
serializer = api.Serializer()
160168
#resource_name = 'statedocevent'
161169
filtering = {
162170
"id": ALL,
@@ -178,6 +186,7 @@ class ConsensusDocEventResource(ModelResource):
178186
docevent_ptr = ToOneField(DocEventResource, 'docevent_ptr')
179187
class Meta:
180188
queryset = ConsensusDocEvent.objects.all()
189+
serializer = api.Serializer()
181190
#resource_name = 'consensusdocevent'
182191
filtering = {
183192
"id": ALL,
@@ -195,6 +204,7 @@ class DocAliasResource(ModelResource):
195204
document = ToOneField(DocumentResource, 'document')
196205
class Meta:
197206
queryset = DocAlias.objects.all()
207+
serializer = api.Serializer()
198208
#resource_name = 'docalias'
199209
filtering = {
200210
"id": ALL,
@@ -210,6 +220,7 @@ class TelechatDocEventResource(ModelResource):
210220
docevent_ptr = ToOneField(DocEventResource, 'docevent_ptr')
211221
class Meta:
212222
queryset = TelechatDocEvent.objects.all()
223+
serializer = api.Serializer()
213224
#resource_name = 'telechatdocevent'
214225
filtering = {
215226
"id": ALL,
@@ -230,6 +241,7 @@ class DocReminderResource(ModelResource):
230241
type = ToOneField(DocReminderTypeNameResource, 'type')
231242
class Meta:
232243
queryset = DocReminder.objects.all()
244+
serializer = api.Serializer()
233245
#resource_name = 'docreminder'
234246
filtering = {
235247
"id": ALL,
@@ -247,6 +259,7 @@ class LastCallDocEventResource(ModelResource):
247259
docevent_ptr = ToOneField(DocEventResource, 'docevent_ptr')
248260
class Meta:
249261
queryset = LastCallDocEvent.objects.all()
262+
serializer = api.Serializer()
250263
#resource_name = 'lastcalldocevent'
251264
filtering = {
252265
"id": ALL,
@@ -267,6 +280,7 @@ class NewRevisionDocEventResource(ModelResource):
267280
docevent_ptr = ToOneField(DocEventResource, 'docevent_ptr')
268281
class Meta:
269282
queryset = NewRevisionDocEvent.objects.all()
283+
serializer = api.Serializer()
270284
#resource_name = 'newrevisiondocevent'
271285
filtering = {
272286
"id": ALL,
@@ -287,6 +301,7 @@ class WriteupDocEventResource(ModelResource):
287301
docevent_ptr = ToOneField(DocEventResource, 'docevent_ptr')
288302
class Meta:
289303
queryset = WriteupDocEvent.objects.all()
304+
serializer = api.Serializer()
290305
#resource_name = 'writeupdocevent'
291306
filtering = {
292307
"id": ALL,
@@ -307,6 +322,7 @@ class InitialReviewDocEventResource(ModelResource):
307322
docevent_ptr = ToOneField(DocEventResource, 'docevent_ptr')
308323
class Meta:
309324
queryset = InitialReviewDocEvent.objects.all()
325+
serializer = api.Serializer()
310326
#resource_name = 'initialreviewdocevent'
311327
filtering = {
312328
"id": ALL,
@@ -328,6 +344,7 @@ class BallotDocEventResource(ModelResource):
328344
ballot_type = ToOneField(BallotTypeResource, 'ballot_type')
329345
class Meta:
330346
queryset = BallotDocEvent.objects.all()
347+
serializer = api.Serializer()
331348
#resource_name = 'ballotdocevent'
332349
filtering = {
333350
"id": ALL,
@@ -348,6 +365,7 @@ class RelatedDocumentResource(ModelResource):
348365
relationship = ToOneField(DocRelationshipNameResource, 'relationship')
349366
class Meta:
350367
queryset = RelatedDocument.objects.all()
368+
serializer = api.Serializer()
351369
#resource_name = 'relateddocument'
352370
filtering = {
353371
"id": ALL,
@@ -375,6 +393,7 @@ class DocHistoryResource(ModelResource):
375393
authors = ToManyField(EmailResource, 'authors', null=True)
376394
class Meta:
377395
queryset = DocHistory.objects.all()
396+
serializer = api.Serializer()
378397
#resource_name = 'dochistory'
379398
filtering = {
380399
"id": ALL,
@@ -416,6 +435,7 @@ class BallotPositionDocEventResource(ModelResource):
416435
pos = ToOneField(BallotPositionNameResource, 'pos')
417436
class Meta:
418437
queryset = BallotPositionDocEvent.objects.all()
438+
serializer = api.Serializer()
419439
#resource_name = 'ballotpositiondocevent'
420440
filtering = {
421441
"id": ALL,
@@ -441,6 +461,7 @@ class DocHistoryAuthorResource(ModelResource):
441461
author = ToOneField(EmailResource, 'author')
442462
class Meta:
443463
queryset = DocHistoryAuthor.objects.all()
464+
serializer = api.Serializer()
444465
#resource_name = 'dochistoryauthor'
445466
filtering = {
446467
"id": ALL,
@@ -457,6 +478,7 @@ class RelatedDocHistoryResource(ModelResource):
457478
relationship = ToOneField(DocRelationshipNameResource, 'relationship')
458479
class Meta:
459480
queryset = RelatedDocHistory.objects.all()
481+
serializer = api.Serializer()
460482
#resource_name = 'relateddochistory'
461483
filtering = {
462484
"id": ALL,

0 commit comments

Comments
 (0)