Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1import json 

2import traceback 

3from typing import Sequence 

4from django.conf.urls import url 

5from django.contrib import admin 

6from django.contrib import messages 

7from django.urls import ResolverMatch, reverse 

8from django.utils.html import format_html 

9from django.utils.safestring import mark_safe 

10from django.utils.timezone import now 

11from django.utils.translation import gettext_lazy as _ 

12from jutil.admin import ModelAdminBase 

13from jsanctions.models import ( 

14 SubjectType, 

15 Regulation, 

16 RegulationSummary, 

17 Remark, 

18 NameAlias, 

19 SanctionEntity, 

20 BirthDate, 

21 Identification, 

22 Citizenship, 

23 Address, 

24 SanctionsListFile, 

25) 

26 

27 

28class SanctionsListAdminBase(ModelAdminBase): 

29 exclude = () 

30 save_on_top = False 

31 

32 

33class SubjectTypeAdmin(SanctionsListAdminBase): 

34 exclude = () 

35 list_display = ( 

36 "classification_code", 

37 "code", 

38 ) 

39 

40 

41class SanctionsListFileAdmin(ModelAdminBase): 

42 save_on_top = False 

43 

44 list_display = [ 

45 "created", 

46 "generation_date", 

47 "imported", 

48 "file", 

49 "list_type", 

50 "entities", 

51 ] 

52 

53 fields = [ 

54 "created", 

55 "generation_date", 

56 "imported", 

57 "file", 

58 "list_type", 

59 "entities", 

60 ] 

61 

62 readonly_fields = [ 

63 "created", 

64 "generation_date", 

65 "imported", 

66 "list_type", 

67 "entities", 

68 ] 

69 

70 raw_id_fields = () 

71 

72 list_filter = [ 

73 "list_type", 

74 ] 

75 

76 date_hierarchy = "created" 

77 

78 def entities(self, obj): 

79 assert isinstance(obj, SanctionsListFile) 

80 return format_html('<a href="{}">{}</a>', reverse('admin:jsanctions_sanctionentity_source_changelist', args=[obj.id]), obj.sanctionentity_set.count()) 

81 

82 entities.short_description = _("sanction entities") 

83 

84 

85class RemarkAdmin(SanctionsListAdminBase): 

86 raw_id_fields = ("container",) 

87 list_display = ( 

88 "id", 

89 "text_brief", 

90 ) 

91 

92 

93class RemarkInlineAdmin(admin.TabularInline): 

94 model = Remark 

95 fk_name = "container" 

96 extra = 0 

97 fields = ("text",) 

98 

99 

100class SanctionEntitySubFieldAdminBase(SanctionsListAdminBase): 

101 raw_id_fields: Sequence[str] = ("sanction",) 

102 

103 

104class SanctionEntityInlineAdmin(admin.StackedInline): 

105 fk_name = "sanction" 

106 extra = 0 

107 

108 

109class NameAliasAdmin(SanctionEntitySubFieldAdminBase): 

110 raw_id_fields = ( 

111 "sanction", 

112 "regulation_summary", 

113 ) 

114 

115 

116class NameAliasInlineAdmin(SanctionEntityInlineAdmin): 

117 model = NameAlias 

118 fields = ( 

119 "first_name", 

120 "middle_name", 

121 "last_name", 

122 "whole_name", 

123 "name_language", 

124 "function", 

125 "title", 

126 "regulation_language", 

127 "logical_id", 

128 "regulation_summary", 

129 ) 

130 raw_id_fields = ( 

131 "sanction", 

132 "regulation_summary", 

133 ) 

134 

135 

136class BirthDateAdmin(SanctionEntitySubFieldAdminBase): 

137 list_display = ( 

138 "id", 

139 "sanction", 

140 "birth_date", 

141 ) 

142 search_fields = ("birth_date",) 

143 

144 

145class BirthDateInlineAdmin(SanctionEntityInlineAdmin): 

146 model = BirthDate 

147 fields = ( 

148 "circa", 

149 "calendar_type", 

150 "city", 

151 "zip_code", 

152 "birth_date", 

153 "day_of_month", 

154 "month_of_year", 

155 "year", 

156 "region", 

157 "place", 

158 "country_iso2_code", 

159 "country_description", 

160 "regulation_language", 

161 "logical_id", 

162 ) 

163 

164 

165class AddressAdmin(SanctionEntitySubFieldAdminBase): 

166 list_display = ( 

167 "id", 

168 "sanction", 

169 "street", 

170 "city", 

171 "region", 

172 "country_iso2_code", 

173 ) 

174 search_fields = ( 

175 "street", 

176 "city", 

177 "region", 

178 "country_iso2_code", 

179 ) 

180 list_filter = ("country_iso2_code",) 

181 

182 

183class AddressInlineAdmin(SanctionEntityInlineAdmin): 

184 model = Address 

185 fields = ( 

186 "city", 

187 "street", 

188 "po_box", 

189 "zip_code", 

190 "as_at_listing_time", 

191 "place", 

192 "region", 

193 "country_iso2_code", 

194 "country_description", 

195 "regulation_language", 

196 "logical_id", 

197 "regulation_summary", 

198 ) 

199 raw_id_fields = ("regulation_summary",) 

200 

201 

202class IdentificationAdmin(SanctionEntitySubFieldAdminBase): 

203 raw_id_fields = ( 

204 "sanction", 

205 "regulation_summary", 

206 ) 

207 

208 

209class IdentificationInlineAdmin(SanctionEntityInlineAdmin): 

210 model = Identification 

211 fields = ( 

212 "diplomatic", 

213 "known_expired", 

214 "known_false", 

215 "reported_lost", 

216 "revoked_by_issuer", 

217 "issued_by", 

218 "latin_number", 

219 "name_on_document", 

220 "number", 

221 "region", 

222 "country_iso2_code", 

223 "country_description", 

224 "identification_type_code", 

225 "identification_type_description", 

226 "regulation_language", 

227 "logical_id", 

228 "regulation_summary", 

229 ) 

230 raw_id_fields = ("regulation_summary",) 

231 

232 

233class CitizenshipAdmin(SanctionEntitySubFieldAdminBase): 

234 raw_id_fields = ( 

235 "sanction", 

236 "regulation_summary", 

237 ) 

238 

239 

240class CitizenshipInlineAdmin(SanctionEntityInlineAdmin): 

241 model = Citizenship 

242 fields = ( 

243 "region", 

244 "country_iso2_code", 

245 "country_description", 

246 "regulation_language", 

247 "logical_id", 

248 "regulation_summary", 

249 ) 

250 raw_id_fields = ( 

251 "sanction", 

252 "regulation_summary", 

253 ) 

254 

255 

256class RegulationInlineAdmin(SanctionEntityInlineAdmin): 

257 model = Regulation 

258 fields = ( 

259 "regulation_type", 

260 "organisation_type", 

261 "publication_date", 

262 "publication_url", 

263 "entry_into_force_date", 

264 "number_title", 

265 "programme", 

266 "logical_id", 

267 ) 

268 

269 

270class RegulationSummaryAdmin(SanctionsListAdminBase): 

271 exclude = () 

272 date_hierarchy = "publication_date" 

273 search_fields = ( 

274 "number_title", 

275 "publication_date__year", 

276 ) 

277 list_display = ( 

278 "id", 

279 "regulation_type", 

280 "number_title", 

281 "publication_date", 

282 "publication_url", 

283 ) 

284 

285 

286class DecadeBornListFilter(admin.SimpleListFilter): 

287 title = _("decade born") 

288 parameter_name = "born" 

289 

290 def lookups(self, request, model_admin): 

291 opts = [ 

292 ("-1919", "-1919"), 

293 ] 

294 begin = 1920 

295 this_year = now().year 

296 while begin <= this_year: 

297 end = begin + 9 

298 if BirthDate.objects.filter(year__gte=begin, year__lte=end).first(): 

299 value = "{}-{}".format(begin, end) 

300 label = "{} - {}".format(begin, end) 

301 opts.append((value, label)) 

302 begin += 10 

303 return opts 

304 

305 def queryset(self, request, queryset): 

306 try: 

307 if self.value(): 

308 begin, end = self.value().split("-") 

309 if begin: 

310 queryset = queryset.filter(birthdate__year__gte=int(begin)) 

311 if end: 

312 queryset = queryset.filter(birthdate__year__lte=int(end)) 

313 except Exception as e: 

314 messages.error(request, str(e)) 

315 queryset = SanctionEntity.objects.none() 

316 return queryset 

317 

318 

319class AddressCountryFilter(admin.SimpleListFilter): 

320 title = _("residence country") 

321 parameter_name = "rcountry" 

322 

323 def lookups(self, request, model_admin): 

324 opts = [] 

325 for obj in Address.objects.distinct("country_iso2_code"): 

326 assert isinstance(obj, Address) 

327 opts.append((obj.country_iso2_code, obj.country_description)) 

328 return opts 

329 

330 def queryset(self, request, queryset): 

331 try: 

332 country = self.value() 

333 if country: 

334 queryset = SanctionEntity.objects.filter(address__country_iso2_code=country) 

335 except Exception as e: 

336 messages.error(request, str(e)) 

337 queryset = SanctionEntity.objects.none() 

338 return queryset 

339 

340 

341class CitizenshipCountryFilter(admin.SimpleListFilter): 

342 title = _("citizenship country") 

343 parameter_name = "ccountry" 

344 

345 def lookups(self, request, model_admin): 

346 opts = [] 

347 for obj in Citizenship.objects.distinct("country_iso2_code"): 

348 assert isinstance(obj, Citizenship) 

349 opts.append((obj.country_iso2_code, obj.country_description)) 

350 return opts 

351 

352 def queryset(self, request, queryset): 

353 try: 

354 country = self.value() 

355 if country: 

356 queryset = SanctionEntity.objects.filter(citizenship__country_iso2_code=country) 

357 except Exception as e: 

358 messages.error(request, str(e)) 

359 queryset = SanctionEntity.objects.none() 

360 return queryset 

361 

362 

363class SanctionEntityAdmin(SanctionsListAdminBase): 

364 search_fields = ( 

365 "namealias__whole_name__icontains", 

366 "eu_reference_number__iexact", 

367 "birthdate__year__iexact", 

368 "birthdate__birth_date__iexact", 

369 ) 

370 inlines = ( 

371 NameAliasInlineAdmin, 

372 AddressInlineAdmin, 

373 IdentificationInlineAdmin, 

374 CitizenshipInlineAdmin, 

375 BirthDateInlineAdmin, 

376 RemarkInlineAdmin, 

377 RegulationInlineAdmin, 

378 ) 

379 raw_id_fields = ( 

380 "source", 

381 "subject_type", 

382 ) 

383 list_display = ( 

384 "id", 

385 "source", 

386 "designation_details", 

387 "name_aliases", 

388 "birth_year", 

389 "united_nation_id", 

390 "eu_reference_number", 

391 "logical_id", 

392 "subject_type", 

393 ) 

394 list_filter = ( 

395 "subject_type", 

396 DecadeBornListFilter, 

397 AddressCountryFilter, 

398 CitizenshipCountryFilter, 

399 ) 

400 fields = [ 

401 'source', 

402 'designation_details', 

403 'united_nation_id', 

404 'eu_reference_number', 

405 'logical_id', 

406 'subject_type', 

407 'data_fmt', 

408 ] 

409 readonly_fields = [ 

410 'data_fmt', 

411 ] 

412 

413 def data_fmt(self, obj) -> str: 

414 try: 

415 return mark_safe("<pre>" + json.dumps(obj.data, indent=4, sort_keys=True) + "</pre>") 

416 except Exception: 

417 return mark_safe("<pre>" + traceback.format_exc() + "</pre>") 

418 

419 data_fmt.short_description = _('data') # type: ignore 

420 

421 def name_aliases(self, obj) -> str: 

422 assert isinstance(obj, SanctionEntity) 

423 all_names = ", ".join([e.whole_name for e in obj.namealias_set.all()]) 

424 return all_names if len(all_names) < 64 else all_names[:64] + '...' 

425 

426 name_aliases.short_description = _("name aliases") # type: ignore 

427 

428 def birth_year(self, obj) -> str: 

429 assert isinstance(obj, SanctionEntity) 

430 return ", ".join([str(e.year) for e in obj.birthdate_set.all().distinct("year")]) 

431 

432 birth_year.short_description = _("birth year") # type: ignore 

433 

434 def get_queryset(self, request): 

435 rm = request.resolver_match 

436 assert isinstance(rm, ResolverMatch) 

437 qs = super().get_queryset(request) 

438 source_id = rm.kwargs.get("source_id", None) 

439 if source_id: 

440 qs = qs.filter(source_id=source_id) 

441 return qs 

442 

443 def get_urls(self): 

444 info = self.model._meta.app_label, self.model._meta.model_name # type: ignore # noqa 

445 return [ 

446 url( 

447 r"^by-source/(?P<source_id>\d+)/$", 

448 self.admin_site.admin_view(self.kw_changelist_view), 

449 name="%s_%s_source_changelist" % info, 

450 ), 

451 ] + super().get_urls() 

452 

453 

454admin.site.register(SanctionsListFile, SanctionsListFileAdmin) 

455admin.site.register(SubjectType, SubjectTypeAdmin) 

456admin.site.register(RegulationSummary, RegulationSummaryAdmin) 

457admin.site.register(SanctionEntity, SanctionEntityAdmin)