This repository has been archived by the owner on Apr 25, 2023. It is now read-only.
forked from ofri/Open-Knesset
-
Notifications
You must be signed in to change notification settings - Fork 175
/
api.py
executable file
·279 lines (232 loc) · 9.92 KB
/
api.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# encoding: utf-8
'''
API for the laws app
'''
import logging
from django.core.urlresolvers import reverse
from tastypie.constants import ALL
import tastypie.fields as fields
from dateutil import parser
from agendas.templatetags.agendas_tags import agendas_for
from apis.resources.base import BaseResource
from mks.api import MemberResource
from models import Law, Bill, Vote, VoteAction, PrivateProposal
from simple.management.commands.syncdata_globals import p_explanation
from datetime import datetime, timedelta
logger = logging.getLogger("open-knesset.laws.api")
class LawResource(BaseResource):
class Meta(BaseResource.Meta):
queryset = Law.objects.all()
allowed_methods = ['get']
class VoteActionResource(BaseResource):
class Meta(BaseResource.Meta):
queryset = VoteAction.objects.all()
allowed_methods = ['get']
excludes = ['type', 'id']
include_resource_uri = False
filtering = {
'against_own_bill': ALL,
}
list_fields = [
'member', 'party', 'vote', 'against_party', 'against_coalition', 'against_opposition', 'against_own_bill',
'member_title', 'vote_title', 'member_url', 'vote_url', 'vote_time'
]
vote_type = fields.CharField('type', null=True)
member = fields.ToOneField(MemberResource, 'member', full=False)
party = fields.ToOneField('mks.api.PartyResource', 'party', full=False)
vote = fields.ToOneField('laws.api.VoteResource', 'vote', full=False)
member_title = fields.CharField('member')
vote_title = fields.CharField('vote')
member_url = fields.CharField('member__get_absolute_url')
vote_url = fields.CharField('vote__get_absolute_url')
vote_time = fields.DateTimeField('vote__time')
class VoteResource(BaseResource):
class Meta(BaseResource.Meta):
queryset = Vote.objects.all()
allowed_methods = ['get']
list_fields = [
'time', 'title', 'vote_type', 'votes_count', 'for_votes_count',
'against_votes_count', 'meeting_number', 'vote_number',
'importance', 'controversy', 'against_party ', 'against_coalition',
'against_opposition', 'against_own_bill',
]
filtering = dict(tag=('exact'),
member=ALL,
member_for=ALL,
member_against=ALL,
from_date=ALL,
to_date=ALL)
votes = fields.ToManyField(VoteActionResource,
attribute=lambda bundle: VoteAction.objects.filter(
vote=bundle.obj).select_related('member'),
null=True,
full=True)
agendas = fields.ListField()
tags = fields.ToManyField('auxiliary.api.TagResource',
attribute=lambda t: t.obj.tags,
null=True,
full=False)
def build_filters(self, filters={}):
orm_filters = super(VoteResource, self).build_filters(filters)
if 'tag' in filters:
# hard-coded the __in filter. not great, but works.
orm_filters["tagged_items__tag__in"] = \
filters["tag"].split(',')
if 'from_date' in filters and filters.get('from_date'):
orm_filters["time__gte"] = filters['from_date']
if 'to_date' in filters:
# the to_date needs to be incremented by a day since when humans say to_date=2014-07-30 they
# actually mean midnight between 30 to 31. python on the other hand interperts this as midnight between
# 29 and 30
to_date = parser.parse(filters["to_date"]) + timedelta(days=1)
orm_filters["time__lte"] = to_date.strftime("%Y-%m-%d")
return orm_filters
def dehydrate_agendas(self, bundle):
agendavotes = bundle.obj.agendavotes.select_related('agenda')
result = []
for avote in agendavotes:
agenda = avote.agenda
resource_uri = reverse(
'api_dispatch_detail',
kwargs={
'resource_name': 'agenda', 'api_name': 'v2',
'pk': agenda.pk})
agenda_bundle = {
'name': agenda.name,
'image': agenda.image.url if agenda.image else None,
'resource_uri': resource_uri,
'score': avote.score,
'importance': avote.importance,
'reasoning': avote.reasoning,
}
result.append(agenda_bundle)
return result
class PrivateProposalResource(BaseResource):
class Meta(BaseResource.Meta):
queryset = PrivateProposal.objects.all()
allowed_methods = ['get']
class BillAgendaResource(BaseResource): pass
def detailed_agendas(agenda_list):
result = []
for xagenda in agenda_list:
agenda = xagenda.agenda
resource_uri = reverse(
'api_dispatch_detail',
kwargs={
'resource_name': 'agenda', 'api_name': 'v2',
'pk': agenda.pk})
result.append({
'name': agenda.name,
'image': agenda.image.url if agenda.image else None,
'resource_uri': resource_uri,
'public_owner_name': agenda.public_owner_name,
'reasoning': xagenda.reasoning,
'score': xagenda.score,
'importance': xagenda.importance,
})
return result
class BillResource(BaseResource):
''' Bill API '''
class Meta(BaseResource.Meta):
queryset = Bill.objects.all()
allowed_methods = ['get']
ordering = ['stage_date', 'title']
filtering = dict(stage=ALL, proposer=ALL, title=ALL, full_title=ALL)
list_fields = [
'title', 'full_title', 'popular_name', 'law', 'stage',
'stage_date'
]
include_absolute_url = True
limit = 20
explanation = fields.CharField()
legal_code = fields.CharField()
proposers = fields.ToManyField(MemberResource,
'proposers',
full=False)
pre_votes = fields.ToManyField(VoteResource,
'pre_votes',
null=True,
full=False)
first_vote = fields.ToOneField(VoteResource,
'first_vote',
null=True,
full=False)
approval_vote = fields.ToOneField(VoteResource,
'approval_vote',
null=True,
full=False)
proposals = fields.ToManyField(PrivateProposalResource,
'proposals',
null=True,
full=True)
tags = fields.ToManyField('auxiliary.api.TagResource',
attribute=lambda t: t.obj.tags,
null=True,
full=False)
# XXX : this adds the following select phrases
# [sql] SELECT ...
# FROM "agendas_agendabill"
# WHERE ("agendas_agendabill"."agenda_id" IN
# (SELECT ...
# FROM "agendas_agenda"
# WHERE "agendas_agenda"."is_public" = TRUE)
# AND "agendas_agendabill"."bill_id" = XXX)
# [sql] SELECT ...
# FROM "agendas_agenda"
# WHERE "agendas_agenda"."id" = YYY
agendas = fields.ToManyField(BillAgendaResource,
'agendas',
null=True,
full=False)
def dehydrate_agendas(self, bundle):
result = None
try:
result = dict()
# fast-written and ugly code
agendas_detailes = agendas_for(bundle.request.user, bundle.obj, 'bill')
result["agenda_list"] = detailed_agendas(agendas_detailes["agendas"])
result["suggest_agendas"] = agendas_detailes[
"suggest_agendas"] # XXX : should i call detailed_agendas here too?
# XXX : there was no data examples here and i dont understand the data-structure that good. there should probably be a special handling for forms
result["formset"] = agendas_detailes["formset"]
result["suggested_agendas"] = agendas_detailes[
"suggested_agendas"] # XXX : should i call detailed_agendas here three?
result["suggest_agendas_login"] = agendas_detailes["suggest_agendas_login"]
return result
except:
logging.exception('Got exception dehydrating agendas')
return None
def dehydrate_explanation(self, bundle):
result = None
try:
result = self.get_src_parts(bundle)[1]
return result # Looks like this is missing :)
except:
logging.exception('Got exception dehydrating explanation')
return ""
# TODO: do we need this here????
# return result
def dehydrate_legal_code(self, bundle):
return self.get_src_parts(bundle)[0]
def dehydrate_stage(self, bundle):
return bundle.obj.get_stage_display()
def get_src_parts(self, bundle):
try:
return bundle.src_parts
except AttributeError:
parts = ['', '']
bill = bundle.obj
try:
ps = bill.proposals.order_by('-date')[0]
if ps.content_html:
parts = ps.content_html.split(p_explanation)
except IndexError:
pass
bundle.src_parts = parts
return parts
def build_filters(self, filters=None):
filters = {} if not filters else filters
orm_filters = super(BillResource, self).build_filters(filters)
if 'proposer' in filters:
orm_filters["proposers"] = filters['proposer']
return orm_filters