示例#1
0
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'))
示例#2
0
    }
    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...')
)
示例#3
0
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')
示例#4
0
文件: admin.py 项目: tborich/froide
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..."))
示例#5
0
    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"]}