class DocumentAdmin(DocumentBaseAdmin): raw_id_fields = DocumentBaseAdmin.raw_id_fields + ( 'original', 'foirequest', 'publicbody', 'team') list_filter = DocumentBaseAdmin.list_filter + ( ('foirequest', ForeignKeyFilter), ('publicbody', ForeignKeyFilter), ('user', ForeignKeyFilter), ('team', ForeignKeyFilter), ) actions = (DocumentBaseAdmin.actions) add_document_to_collection = make_choose_object_action( DocumentCollection, execute_add_document_to_collection, _('Add documents to collection'))
} guidance_notification_mail.send( user=user, context=context, subject=subject ) Guidance.objects.filter( id__in=[g.id for g in guidances] ).update(notified=True) def notify_guidance(guidance): if guidance.notified: return notify_users([(guidance.message, GuidanceResult([guidance], 0, 0))]) def execute_assign_guidance(admin, request, queryset, action_obj): from .tasks import add_action_to_queryset_task add_action_to_queryset_task.delay( action_obj.id, list( queryset.values_list('id', flat=True) ) ) assign_guidance = make_choose_object_action( Guidance, execute_assign_guidance, _('Choose guidance action to attach...') )
class PublicBodyBaseAdminMixin: form = PublicBodyAdminForm date_hierarchy = 'updated_at' prepopulated_fields = {"slug": ("name", )} save_on_top = True fieldsets = ( (None, { 'fields': ( 'name', 'slug', 'other_names', 'classification', 'url', 'email', 'fax', 'contact', 'address', ) }), (_('Context'), { 'fields': ( 'jurisdiction', 'laws', 'request_note', 'categories', 'description', 'file_index', 'org_chart', ), }), (_('Hierachy'), { 'classes': ('collapse', ), 'fields': ('parent', 'root', 'depth'), }), (_('Geo'), { 'classes': ('collapse', ), 'fields': ('regions', 'geo'), }), (_('Advanced'), { 'classes': ('collapse', ), 'fields': ('site', 'number_of_requests', 'website_dump', 'wikidata_item', 'source_reference', 'extra_data', 'change_proposals'), }), (_('Meta'), { 'fields': ( '_created_by', 'created_at', '_updated_by', 'updated_at', ), }), ) list_display = ('name', 'email', 'url', 'classification', 'jurisdiction', 'category_list', 'request_count') list_filter = (make_emptyfilter('change_proposals', _('Has change proposals'), empty_value=dict), 'jurisdiction', ('classification', TreeRelatedFieldListFilter), 'categories', make_nullfilter('geo', _('Has geo coordinates')), make_nullfilter('regions', _('Has regions')), make_emptyfilter('email', 'E-Mail'), make_emptyfilter('fax', 'Fax')) filter_horizontal = ('laws', ) list_max_show_all = 5000 search_fields = ['name', 'other_names', 'description', 'email'] exclude = ('confirmed', ) raw_id_fields = ('parent', 'root', '_created_by', '_updated_by', 'regions', 'classification') readonly_fields = ('_created_by', 'created_at', '_updated_by', 'updated_at') actions = ( 'assign_classification', 'replace_publicbody', 'export_csv', 'remove_from_index', 'tag_all', 'show_georegions', 'validate_publicbodies', ) tag_all = make_batch_tag_action(field='categories', autocomplete_url=CATEGORY_AUTOCOMPLETE_URL) assign_classification = make_choose_object_action( Classification, execute_assign_classification, _('Assign classification...')) replace_publicbody = make_choose_object_action( PublicBody, execute_replace_publicbody, _('Replace public bodies with...')) def get_queryset(self, request): qs = super(PublicBodyBaseAdminMixin, self).get_queryset(request) qs = qs.annotate(request_count=Count('foirequest')) qs = qs.select_related('classification', 'jurisdiction') return qs def request_count(self, obj): return obj.request_count request_count.admin_order_field = 'request_count' request_count.short_description = _('requests') def get_urls(self): urls = super(PublicBodyBaseAdminMixin, self).get_urls() my_urls = [ url(r'^import/$', self.admin_site.admin_view(self.import_csv), name='publicbody-publicbody-import_csv'), url(r'^geo-match/$', self.admin_site.admin_view(self.geo_match), name='publicbody-publicbody-geo_match'), ] return my_urls + urls def import_csv(self, request): if not request.method == 'POST': raise PermissionDenied if not self.has_change_permission(request): raise PermissionDenied importer = CSVImporter() url = request.POST.get('url') csv_file = request.FILES.get('file') try: if not url and not csv_file: raise ValueError(_('You need to provide a url or a file.')) if url: importer.import_from_url(url) else: importer.import_from_file(csv_file) except Exception as e: self.message_user(request, str(e)) else: self.message_user(request, _('Public Bodies were imported.')) return redirect('admin:publicbody_publicbody_changelist') def geo_match(self, request): from froide.georegion.models import GeoRegion if request.method == 'POST': if not self.has_change_permission(request): raise PermissionDenied data = json.loads(request.body) try: georegion = GeoRegion.objects.get(id=data['georegion']) except GeoRegion.DoesNotExist: return HttpResponse(status=404) try: pb = PublicBody.objects.get(id=data['publicbody']) except PublicBody.DoesNotExist: return HttpResponse(status=404) pb.regions.add(georegion) return HttpResponse(status=201, content=b'{}') opts = self.model._meta config = { 'url': { 'listCategories': reverse('api:category-list'), 'listClassifications': reverse('api:classification-list'), 'listPublicBodies': reverse('api:publicbody-list'), 'searchPublicBody': reverse('api:publicbody-search'), 'listGeoregion': reverse('api:georegion-list'), 'detailGeoregion': reverse('api:georegion-detail', kwargs={'pk': 0}), 'detailJurisdiction': reverse('api:jurisdiction-detail', kwargs={'pk': 0}), 'georegionAdminUrl': reverse('admin:georegion_georegion_change', kwargs={'object_id': 0}), 'publicbodyAdminUrl': reverse('admin:publicbody_publicbody_changelist'), 'publicbodyAdminChangeUrl': reverse('admin:publicbody_publicbody_change', kwargs={'object_id': 0}), 'publicbodyAddAdminUrl': reverse('admin:publicbody_publicbody_add'), } } ctx = { 'app_label': opts.app_label, 'opts': opts, 'config': json.dumps(config) } return render(request, 'publicbody/admin/match_georegions.html', ctx) def save_model(self, request, obj, form, change): obj._updated_by = request.user obj.updated_at = timezone.now() if change is None: obj._created_by = obj._updated_by obj.created_at = obj.updated_at super(PublicBodyBaseAdminMixin, self).save_model(request, obj, form, change) def category_list(self, obj): return ", ".join(o.name for o in obj.categories.all()) def export_csv(self, request, queryset): return export_csv_response(PublicBody.export_csv(queryset)) export_csv.short_description = _("Export to CSV") def remove_from_index(self, request, queryset): from django_elasticsearch_dsl.registries import registry for obj in queryset: registry.delete(obj, raise_on_error=False) self.message_user(request, _("Removed from search index")) remove_from_index.short_description = _("Remove from search index") def show_georegions(self, request, queryset): opts = self.model._meta context = { 'opts': opts, 'media': self.media, 'applabel': opts.app_label, 'no_regions': queryset.filter(regions=None), 'regions': json.dumps({ reg.id: pb.id for pb in queryset.exclude(regions=None) for reg in pb.regions.all() }) } # Display the confirmation page return TemplateResponse(request, 'publicbody/admin/show_georegions.html', context) show_georegions.short_description = _("Show georegions of") def validate_publicbodies(self, request, queryset): csv_stream = dict_to_csv_stream(validate_publicbodies(queryset)) return export_csv_response(csv_stream, name='validation.csv')
class DeferredMessageAdmin(admin.ModelAdmin): model = DeferredMessage list_filter = ('delivered', make_nullfilter('request', _('Has request')), 'spam') search_fields = ( 'recipient', 'sender', ) date_hierarchy = 'timestamp' ordering = ('-timestamp', ) list_display = ( 'recipient', 'timestamp', 'spam', 'delivered', 'sender', 'request_last_message', 'request_status', 'request_page', ) raw_id_fields = ('request', ) actions = [ 'mark_as_spam', 'deliver_no_spam', 'redeliver', 'redeliver_subject', 'close_request' ] save_on_top = True def get_queryset(self, request): qs = super().get_queryset(request) qs = qs.select_related('request') return qs def request_last_message(self, obj): if obj.request: return obj.request.last_message def request_status(self, obj): if obj.request: return obj.request.get_status_display() def request_page(self, obj): if obj.request: return format_html('<a href="{}">{}</a>', obj.request.get_absolute_url(), obj.request.title) def close_request(self, request, queryset): for mes in queryset: mes.request.closed = True mes.request.save() return None close_request.short_description = _('Close associated requests') def redeliver_subject(self, request, queryset): parser = EmailParser() for deferred in queryset: email = parser.parse(BytesIO(deferred.encoded_mail())) match = SUBJECT_REQUEST_ID.search(email.subject) if match is not None: try: req = FoiRequest.objects.get(pk=match.group(1)) deferred.redeliver(req) except FoiRequest.DoesNotExist: continue redeliver_subject.short_description = _("Auto-Redeliver based on subject") def deliver_no_spam(self, request, queryset): for deferred in queryset: if deferred.request is not None: deferred.spam = False if deferred.delivered: deferred.save() else: deferred.redeliver(deferred.request) deliver_no_spam.short_description = _("Deliver and mark as no spam") def mark_as_spam(self, request, queryset): spam_senders = set() marked = 0 deleted = 0 for mes in queryset: if mes.sender in spam_senders: mes.delete() deleted += 1 continue mes.spam = True mes.save() spam_senders.add(mes.sender) marked += 1 self.message_user( request, _("Marked {marked} as spam, deleted {deleted} duplicates.").format( marked=marked, deleted=deleted)) mark_as_spam.short_description = _( "Mark as spam (delete all except one per sender)") redeliver = make_choose_object_action(FoiRequest, execute_redeliver, _("Redeliver to..."))
list_filter = ['is_topic', 'rank'] ordering = ["rank", "name"] search_fields = ["name"] prepopulated_fields = {"slug": ["name"]} class TaggedPublicBodyAdmin(admin.ModelAdmin): raw_id_fields = ('content_object', 'tag') def execute_assign_parent(admin, request, queryset, action_obj): for obj in queryset: obj.move(action_obj, 'sorted-child') assign_classification_parent = make_choose_object_action( Classification, execute_assign_parent, _('Assign parent...')) assign_category_parent = make_choose_object_action(Category, execute_assign_parent, _('Assign parent...')) class ClassificationAdmin(TreeAdmin): fields = ( 'name', 'slug', '_position', '_ref_node_id', ) form = movenodeform_factory(Classification) prepopulated_fields = {"slug": ["name"]}