def delete(request, page_id): page = get_object_or_404(Page, id=page_id) if not page.permissions_for_user(request.user).can_delete(): raise PermissionDenied for fn in hooks.get_hooks('before_delete_page'): result = fn(request, page) if hasattr(result, 'status_code'): return result next_url = get_valid_next_url_from_request(request) if request.method == 'POST': parent_id = page.get_parent().id page.delete() messages.success( request, _("Page '{0}' deleted.").format(page.get_admin_display_title())) for fn in hooks.get_hooks('after_delete_page'): result = fn(request, page) if hasattr(result, 'status_code'): return result if next_url: return redirect(next_url) return redirect('tuiuiuadmin_explore', parent_id) return render( request, 'tuiuiuadmin/pages/confirm_delete.html', { 'page': page, 'descendant_count': page.get_descendant_count(), 'next': next_url, })
def home(request): panels = [ SiteSummaryPanel(request), UpgradeNotificationPanel(request), PagesForModerationPanel(request), RecentEditsPanel(request), ] for fn in hooks.get_hooks('construct_homepage_panels'): fn(request, panels) root_page = get_explorable_root_page(request.user) if root_page: root_site = root_page.get_site() else: root_site = None real_site_name = None if root_site: real_site_name = root_site.site_name if root_site.site_name else root_site.hostname return render(request, "tuiuiuadmin/home.html", { 'root_page': root_page, 'root_site': root_site, 'site_name': real_site_name if real_site_name else settings.TUIUIU_SITE_NAME, 'panels': sorted(panels, key=lambda p: p.order), 'user': request.user })
def test_after_hook(self): def after_hook(): pass with self.register_hook('test_hook_name', after_hook, order=1): hook_fns = hooks.get_hooks('test_hook_name') self.assertEqual(hook_fns, [test_hook, after_hook])
def chooser(request): Document = get_document_model() if permission_policy.user_has_permission(request.user, 'add'): DocumentForm = get_document_form(Document) uploadform = DocumentForm(user=request.user) else: uploadform = None documents = Document.objects.all() # allow hooks to modify the queryset for hook in hooks.get_hooks('construct_document_chooser_queryset'): documents = hook(documents, request) q = None if 'q' in request.GET or 'p' in request.GET or 'collection_id' in request.GET: collection_id = request.GET.get('collection_id') if collection_id: documents = documents.filter(collection=collection_id) searchform = SearchForm(request.GET) if searchform.is_valid(): q = searchform.cleaned_data['q'] documents = documents.search(q) is_searching = True else: documents = documents.order_by('-created_at') is_searching = False # Pagination paginator, documents = paginate(request, documents, per_page=10) return render( request, "tuiuiudocs/chooser/results.html", { 'documents': documents, 'query_string': q, 'is_searching': is_searching, }) else: searchform = SearchForm() collections = Collection.objects.all() if len(collections) < 2: collections = None documents = documents.order_by('-created_at') paginator, documents = paginate(request, documents, per_page=10) return render_modal_workflow( request, 'tuiuiudocs/chooser/chooser.html', 'tuiuiudocs/chooser/chooser.js', { 'documents': documents, 'uploadform': uploadform, 'searchform': searchform, 'collections': collections, 'is_searching': False, })
def setUp(self): # Create a group to edit self.test_group = Group.objects.create(name='test group') self.root_page = Page.objects.get(pk=1) self.root_add_permission = GroupPagePermission.objects.create( page=self.root_page, permission_type='add', group=self.test_group) self.home_page = Page.objects.get(pk=2) # Get the hook-registered permissions, and add one to this group self.registered_permissions = Permission.objects.none() for fn in hooks.get_hooks('register_permissions'): self.registered_permissions = self.registered_permissions | fn() self.existing_permission = self.registered_permissions.order_by( 'pk')[0] self.another_permission = self.registered_permissions.order_by('pk')[1] self.test_group.permissions.add(self.existing_permission) # set up collections to test document permissions self.root_collection = Collection.get_first_root_node() self.evil_plans_collection = self.root_collection.add_child( name="Evil plans") self.add_doc_permission = Permission.objects.get( content_type__app_label='tuiuiudocs', codename='add_document') self.change_doc_permission = Permission.objects.get( content_type__app_label='tuiuiudocs', codename='change_document') GroupCollectionPermission.objects.create( group=self.test_group, collection=self.evil_plans_collection, permission=self.add_doc_permission, ) # Login self.login()
def test_before_hook(self): def before_hook(): pass with self.register_hook('test_hook_name', before_hook, order=-1): hook_fns = hooks.get_hooks('test_hook_name') self.assertEqual(hook_fns, [before_hook, test_hook])
def get_permission_panel_classes(): global _permission_panel_classes if _permission_panel_classes is None: _permission_panel_classes = [GroupPagePermissionFormSet] for fn in hooks.get_hooks('register_group_permission_panel'): _permission_panel_classes.append(fn()) return _permission_panel_classes
def clean(cls, html): if not cls.has_loaded_custom_whitelist_rules: for fn in hooks.get_hooks('construct_whitelister_element_rules'): cls.element_rules = cls.element_rules.copy() cls.element_rules.update(fn()) cls.has_loaded_custom_whitelist_rules = True return super(DbWhitelister, cls).clean(html)
def _search_for_operations(cls): if cls._registered_operations is not None: return operations = [] for fn in hooks.get_hooks('register_image_operations'): operations.extend(fn()) cls._registered_operations = dict(operations)
def hook_output(hook_name): """ Example: {% hook_output 'insert_editor_css' %} Whenever we have a hook whose functions take no parameters and return a string, this tag can be used to output the concatenation of all of those return values onto the page. Note that the output is not escaped - it is the hook function's responsibility to escape unsafe content. """ snippets = [fn() for fn in hooks.get_hooks(hook_name)] return mark_safe(''.join(snippets))
def test_registered_permission(self): permission = Permission.objects.get_by_natural_key( app_label='tests', model='testsetting', codename='change_testsetting') for fn in hooks.get_hooks('register_permissions'): if permission in fn(): break else: self.fail('Change permission for tests.TestSetting not registered')
def get_link_handler(link_type): global LINK_HANDLERS, has_loaded_link_handlers if not has_loaded_link_handlers: for hook in hooks.get_hooks('register_rich_text_link_handler'): handler_name, handler = hook() LINK_HANDLERS[handler_name] = handler has_loaded_link_handlers = True return LINK_HANDLERS[link_type]
def get_embed_handler(embed_type): global EMBED_HANDLERS, has_loaded_embed_handlers if not has_loaded_embed_handlers: for hook in hooks.get_hooks('register_rich_text_embed_handler'): handler_name, handler = hook() EMBED_HANDLERS[handler_name] = handler has_loaded_embed_handlers = True return EMBED_HANDLERS[embed_type]
def get_forms_for_user(user): """ Return a queryset of form pages that this user is allowed to access the submissions for """ editable_forms = UserPagePermissionsProxy(user).editable_pages() editable_forms = editable_forms.filter(content_type__in=get_form_types()) # Apply hooks for fn in hooks.get_hooks('filter_form_submissions_for_user'): editable_forms = fn(user, editable_forms) return editable_forms
def get_collection_contents(self): collection_contents = [ hook(self.instance) for hook in hooks.get_hooks('describe_collection_contents') ] # filter out any hook responses that report that the collection is empty # (by returning None, or a dict with 'count': 0) def is_nonempty(item_type): return item_type and item_type['count'] > 0 return list(filter(is_nonempty, collection_contents))
def serve(request, path): # we need a valid Site object corresponding to this request (set in tuiuiu.tuiuiucore.middleware.SiteMiddleware) # in order to proceed if not request.site: raise Http404 path_components = [component for component in path.split('/') if component] page, args, kwargs = request.site.root_page.specific.route( request, path_components) for fn in hooks.get_hooks('before_serve_page'): result = fn(page, request, args, kwargs) if isinstance(result, HttpResponse): return result return page.serve(request, *args, **kwargs)
def render_html(self, request): menu_items = self.menu_items_for_request(request) # provide a hook for modifying the menu, if construct_hook_name has been set if self.construct_hook_name: for fn in hooks.get_hooks(self.construct_hook_name): fn(request, menu_items) rendered_menu_items = [] for item in sorted(menu_items, key=lambda i: i.order): try: rendered_menu_items.append(item.render_html(request)) except TypeError: # fallback for older render_html methods that don't accept a request arg rendered_menu_items.append(item.render_html(request)) return mark_safe(''.join(rendered_menu_items))
def for_frontend(request, page_id): items = [ EditPageItem(Page.objects.get(id=page_id)), AddPageItem(Page.objects.get(id=page_id)), ] for fn in hooks.get_hooks('construct_tuiuiu_userbar'): fn(request, items) # Render the items rendered_items = [item.render(request) for item in items] # Remove any unrendered items rendered_items = [item for item in rendered_items if item] # Render the edit bird return render(request, 'tuiuiuadmin/userbar/base.html', { 'items': rendered_items, })
def render_html(self, request, current=None): search_areas = self.search_items_for_request(request) # Get query parameter form = SearchForm(request.GET) query = '' if form.is_valid(): query = form.cleaned_data['q'] # provide a hook for modifying the search area, if construct_hook_name has been set if self.construct_hook_name: for fn in hooks.get_hooks(self.construct_hook_name): fn(request, search_areas) rendered_search_areas = [] for item in search_areas: rendered_search_areas.append(item.render_html(request, query, current)) return mark_safe(''.join(rendered_search_areas))
def for_moderation(request, revision_id): items = [ EditPageItem(PageRevision.objects.get(id=revision_id).page), AddPageItem(PageRevision.objects.get(id=revision_id).page), ApproveModerationEditPageItem( PageRevision.objects.get(id=revision_id)), RejectModerationEditPageItem(PageRevision.objects.get(id=revision_id)), ] for fn in hooks.get_hooks('construct_tuiuiu_userbar'): fn(request, items) # Render the items rendered_items = [item.render(request) for item in items] # Remove any unrendered items rendered_items = [item for item in rendered_items if item] # Render the edit bird return render(request, 'tuiuiuadmin/userbar/base.html', { 'items': rendered_items, })
def search(request, parent_page_id=None): # A missing or empty page_type parameter indicates 'all page types' (i.e. descendants of tuiuiucore.page) page_type_string = request.GET.get('page_type') or 'tuiuiucore.page' try: desired_classes = page_models_from_string(page_type_string) except (ValueError, LookupError): raise Http404 pages = Page.objects.all() # allow hooks to modify the queryset for hook in hooks.get_hooks('construct_page_chooser_queryset'): pages = hook(pages, request) search_form = SearchForm(request.GET) if search_form.is_valid() and search_form.cleaned_data['q']: pages = pages.exclude(depth=1 # never include root ) pages = filter_page_type(pages, desired_classes) pages = pages.search(search_form.cleaned_data['q'], fields=['title']) else: pages = pages.none() paginator, pages = paginate(request, pages, per_page=25) for page in pages: page.can_choose = True return render( request, 'tuiuiuadmin/chooser/_search_results.html', shared_context( request, { 'searchform': search_form, 'pages': pages, 'page_type_string': page_type_string, }))
from __future__ import absolute_import, unicode_literals from django.conf.urls import url from tuiuiu.api.v2.router import TuiuiuAPIRouter from tuiuiu.tuiuiucore import hooks from .endpoints import PagesAdminAPIEndpoint admin_api = TuiuiuAPIRouter('tuiuiuadmin_api_v1') admin_api.register_endpoint('pages', PagesAdminAPIEndpoint) for fn in hooks.get_hooks('construct_admin_api'): fn(admin_api) urlpatterns = [ url(r'^v2beta/', admin_api.urls), ]
def copy(request, page_id): page = Page.objects.get(id=page_id) # Parent page defaults to parent of source page parent_page = page.get_parent() # Check if the user has permission to publish subpages on the parent can_publish = parent_page.permissions_for_user( request.user).can_publish_subpage() # Create the form form = CopyForm(request.POST or None, user=request.user, page=page, can_publish=can_publish) next_url = get_valid_next_url_from_request(request) for fn in hooks.get_hooks('before_copy_page'): result = fn(request, page) if hasattr(result, 'status_code'): return result # Check if user is submitting if request.method == 'POST': # Prefill parent_page in case the form is invalid (as prepopulated value for the form field, # because ModelChoiceField seems to not fall back to the user given value) parent_page = Page.objects.get(id=request.POST['new_parent_page']) if form.is_valid(): # Receive the parent page (this should never be empty) if form.cleaned_data['new_parent_page']: parent_page = form.cleaned_data['new_parent_page'] if not page.permissions_for_user(request.user).can_copy_to( parent_page, form.cleaned_data.get('copy_subpages')): raise PermissionDenied # Re-check if the user has permission to publish subpages on the new parent can_publish = parent_page.permissions_for_user( request.user).can_publish_subpage() # Copy the page new_page = page.copy( recursive=form.cleaned_data.get('copy_subpages'), to=parent_page, update_attrs={ 'title': form.cleaned_data['new_title'], 'slug': form.cleaned_data['new_slug'], }, keep_live=(can_publish and form.cleaned_data.get('publish_copies')), user=request.user, ) # Give a success message back to the user if form.cleaned_data.get('copy_subpages'): messages.success( request, _("Page '{0}' and {1} subpages copied.").format( page.get_admin_display_title(), new_page.get_descendants().count())) else: messages.success( request, _("Page '{0}' copied.").format( page.get_admin_display_title())) for fn in hooks.get_hooks('after_copy_page'): result = fn(request, page, new_page) if hasattr(result, 'status_code'): return result # Redirect to explore of parent page if next_url: return redirect(next_url) return redirect('tuiuiuadmin_explore', parent_page.id) return render(request, 'tuiuiuadmin/pages/copy.html', { 'page': page, 'form': form, 'next': next_url, })
def populate(self): for fn in hooks.get_hooks('register_admin_viewset'): viewset = fn() self.register(viewset)
def index(request, parent_page_id=None): if parent_page_id: parent_page = get_object_or_404(Page, id=parent_page_id).specific else: parent_page = Page.get_first_root_node().specific pages = parent_page.get_children().prefetch_related( 'content_type', 'sites_rooted_here') # Get page ordering ordering = request.GET.get('ordering', '-latest_revision_created_at') if ordering not in [ 'title', '-title', 'content_type', '-content_type', 'live', '-live', 'latest_revision_created_at', '-latest_revision_created_at', 'ord' ]: ordering = '-latest_revision_created_at' if ordering == 'ord': # preserve the native ordering from get_children() pass elif ordering == 'latest_revision_created_at': # order by oldest revision first. # Special case NULL entries - these should go at the top of the list. # Do this by annotating with Count('latest_revision_created_at'), # which returns 0 for these pages = pages.annotate( null_position=Count('latest_revision_created_at')).order_by( 'null_position', 'latest_revision_created_at') elif ordering == '-latest_revision_created_at': # order by oldest revision first. # Special case NULL entries - these should go at the end of the list. pages = pages.annotate( null_position=Count('latest_revision_created_at')).order_by( '-null_position', '-latest_revision_created_at') else: pages = pages.order_by(ordering) # Don't paginate if sorting by page order - all pages must be shown to # allow drag-and-drop reordering do_paginate = ordering != 'ord' if do_paginate: # Retrieve pages in their most specific form. # Only do this for paginated listings, as this could potentially be a # very expensive operation when performed on a large queryset. pages = pages.specific() # allow hooks to modify the queryset for hook in hooks.get_hooks('construct_explorer_page_queryset'): pages = hook(parent_page, pages, request) # Pagination if do_paginate: paginator, pages = paginate(request, pages, per_page=50) return render( request, 'tuiuiuadmin/pages/index.html', { 'parent_page': parent_page.specific, 'ordering': ordering, 'pagination_query_params': "ordering=%s" % ordering, 'pages': pages, 'do_paginate': do_paginate, })
def edit(request, page_id): latest_revision = get_object_or_404(Page, id=page_id).get_latest_revision() page = get_object_or_404(Page, id=page_id).get_latest_revision_as_page() parent = page.get_parent() content_type = ContentType.objects.get_for_model(page) page_class = content_type.model_class() page_perms = page.permissions_for_user(request.user) if not page_perms.can_edit(): raise PermissionDenied for fn in hooks.get_hooks('before_edit_page'): result = fn(request, page) if hasattr(result, 'status_code'): return result edit_handler_class = page_class.get_edit_handler() form_class = edit_handler_class.get_form_class(page_class) next_url = get_valid_next_url_from_request(request) errors_debug = None if request.method == 'POST': form = form_class(request.POST, request.FILES, instance=page, parent_page=parent) if form.is_valid() and not page.locked: page = form.save(commit=False) is_publishing = bool(request.POST.get( 'action-publish')) and page_perms.can_publish() is_submitting = bool(request.POST.get('action-submit')) is_reverting = bool(request.POST.get('revision')) # If a revision ID was passed in the form, get that revision so its # date can be referenced in notification messages if is_reverting: previous_revision = get_object_or_404( page.revisions, id=request.POST.get('revision')) # Save revision revision = page.save_revision( user=request.user, submitted_for_moderation=is_submitting, ) # Publish if is_publishing: revision.publish() # Need to reload the page because the URL may have changed, and we # need the up-to-date URL for the "View Live" button. page = page.specific_class.objects.get(pk=page.pk) # Notifications if is_publishing: if page.go_live_at and page.go_live_at > timezone.now(): # Page has been scheduled for publishing in the future if is_reverting: message = _( "Revision from {0} of page '{1}' has been scheduled for publishing." ).format( previous_revision.created_at.strftime( "%d %b %Y %H:%M"), page.get_admin_display_title()) else: message = _( "Page '{0}' has been scheduled for publishing." ).format(page.get_admin_display_title()) messages.success(request, message, buttons=[ messages.button( reverse('tuiuiuadmin_pages:edit', args=(page.id, )), _('Edit')) ]) else: # Page is being published now if is_reverting: message = _( "Revision from {0} of page '{1}' has been published." ).format( previous_revision.created_at.strftime( "%d %b %Y %H:%M"), page.get_admin_display_title()) else: message = _("Page '{0}' has been published.").format( page.get_admin_display_title()) messages.success(request, message, buttons=[ messages.button(page.url, _('View live'), new_window=True), messages.button( reverse('tuiuiuadmin_pages:edit', args=(page_id, )), _('Edit')) ]) elif is_submitting: message = _( "Page '{0}' has been submitted for moderation.").format( page.get_admin_display_title()) messages.success(request, message, buttons=[ messages.button(reverse( 'tuiuiuadmin_pages:view_draft', args=(page_id, )), _('View draft'), new_window=True), messages.button( reverse('tuiuiuadmin_pages:edit', args=(page_id, )), _('Edit')) ]) if not send_notification(page.get_latest_revision().id, 'submitted', request.user.pk): messages.error( request, _("Failed to send notifications to moderators")) else: # Saving if is_reverting: message = _( "Page '{0}' has been replaced with revision from {1}." ).format( page.get_admin_display_title(), previous_revision.created_at.strftime( "%d %b %Y %H:%M")) else: message = _("Page '{0}' has been updated.").format( page.get_admin_display_title()) messages.success(request, message) for fn in hooks.get_hooks('after_edit_page'): result = fn(request, page) if hasattr(result, 'status_code'): return result if is_publishing or is_submitting: # we're done here - redirect back to the explorer if next_url: # redirect back to 'next' url if present return redirect(next_url) # redirect back to the explorer return redirect('tuiuiuadmin_explore', page.get_parent().id) else: # Just saving - remain on edit page for further edits target_url = reverse('tuiuiuadmin_pages:edit', args=[page.id]) if next_url: # Ensure the 'next' url is passed through again if present target_url += '?next=%s' % urlquote(next_url) return redirect(target_url) else: if page.locked: messages.error( request, _("The page could not be saved as it is locked")) else: messages.validation_error( request, _("The page could not be saved due to validation errors"), form) edit_handler = edit_handler_class(instance=page, form=form) errors_debug = (repr(edit_handler.form.errors) + repr( [(name, formset.errors) for (name, formset) in edit_handler.form.formsets.items() if formset.errors])) has_unsaved_changes = True else: form = form_class(instance=page, parent_page=parent) edit_handler = edit_handler_class(instance=page, form=form) has_unsaved_changes = False # Check for revisions still undergoing moderation and warn if latest_revision and latest_revision.submitted_for_moderation: buttons = [] if page.live: buttons.append( messages.button( reverse('tuiuiuadmin_pages:revisions_compare', args=(page.id, 'live', latest_revision.id)), _('Compare with live version'))) messages.warning(request, _("This page is currently awaiting moderation"), buttons=buttons) return render( request, 'tuiuiuadmin/pages/edit.html', { 'page': page, 'content_type': content_type, 'edit_handler': edit_handler, 'errors_debug': errors_debug, 'preview_modes': page.preview_modes, 'form': form, 'next': next_url, 'has_unsaved_changes': has_unsaved_changes, })
def create(request, content_type_app_name, content_type_model_name, parent_page_id): parent_page = get_object_or_404(Page, id=parent_page_id).specific parent_page_perms = parent_page.permissions_for_user(request.user) if not parent_page_perms.can_add_subpage(): raise PermissionDenied try: content_type = ContentType.objects.get_by_natural_key( content_type_app_name, content_type_model_name) except ContentType.DoesNotExist: raise Http404 # Get class page_class = content_type.model_class() # Make sure the class is a descendant of Page if not issubclass(page_class, Page): raise Http404 # page must be in the list of allowed subpage types for this parent ID if page_class not in parent_page.creatable_subpage_models(): raise PermissionDenied if not page_class.can_create_at(parent_page): raise PermissionDenied for fn in hooks.get_hooks('before_create_page'): result = fn(request, parent_page, page_class) if hasattr(result, 'status_code'): return result page = page_class(owner=request.user) edit_handler_class = page_class.get_edit_handler() form_class = edit_handler_class.get_form_class(page_class) next_url = get_valid_next_url_from_request(request) if request.method == 'POST': form = form_class(request.POST, request.FILES, instance=page, parent_page=parent_page) if form.is_valid(): page = form.save(commit=False) is_publishing = bool(request.POST.get( 'action-publish')) and parent_page_perms.can_publish_subpage() is_submitting = bool(request.POST.get('action-submit')) if not is_publishing: page.live = False # Save page parent_page.add_child(instance=page) # Save revision revision = page.save_revision( user=request.user, submitted_for_moderation=is_submitting, ) # Publish if is_publishing: revision.publish() # Notifications if is_publishing: if page.go_live_at and page.go_live_at > timezone.now(): messages.success( request, _("Page '{0}' created and scheduled for publishing." ).format(page.get_admin_display_title()), buttons=[ messages.button( reverse('tuiuiuadmin_pages:edit', args=(page.id, )), _('Edit')) ]) else: messages.success( request, _("Page '{0}' created and published.").format( page.get_admin_display_title()), buttons=[ messages.button(page.url, _('View live'), new_window=True), messages.button( reverse('tuiuiuadmin_pages:edit', args=(page.id, )), _('Edit')) ]) elif is_submitting: messages.success( request, _("Page '{0}' created and submitted for moderation." ).format(page.get_admin_display_title()), buttons=[ messages.button(reverse('tuiuiuadmin_pages:view_draft', args=(page.id, )), _('View draft'), new_window=True), messages.button( reverse('tuiuiuadmin_pages:edit', args=(page.id, )), _('Edit')) ]) if not send_notification(page.get_latest_revision().id, 'submitted', request.user.pk): messages.error( request, _("Failed to send notifications to moderators")) else: messages.success( request, _("Page '{0}' created.").format( page.get_admin_display_title())) for fn in hooks.get_hooks('after_create_page'): result = fn(request, page) if hasattr(result, 'status_code'): return result if is_publishing or is_submitting: # we're done here if next_url: # redirect back to 'next' url if present return redirect(next_url) # redirect back to the explorer return redirect('tuiuiuadmin_explore', page.get_parent().id) else: # Just saving - remain on edit page for further edits target_url = reverse('tuiuiuadmin_pages:edit', args=[page.id]) if next_url: # Ensure the 'next' url is passed through again if present target_url += '?next=%s' % urlquote(next_url) return redirect(target_url) else: messages.validation_error( request, _("The page could not be created due to validation errors"), form) edit_handler = edit_handler_class(instance=page, form=form) has_unsaved_changes = True else: signals.init_new_page.send(sender=create, page=page, parent=parent_page) form = form_class(instance=page, parent_page=parent_page) edit_handler = edit_handler_class(instance=page, form=form) has_unsaved_changes = False return render( request, 'tuiuiuadmin/pages/create.html', { 'content_type': content_type, 'page_class': page_class, 'parent_page': parent_page, 'edit_handler': edit_handler, 'preview_modes': page.preview_modes, 'form': form, 'next': next_url, 'has_unsaved_changes': has_unsaved_changes, })
def dropdown_buttons(self): button_hooks = hooks.get_hooks(self.hook_name) return sorted( itertools.chain.from_iterable( hook(self.page, self.page_perms, self.is_parent) for hook in button_hooks))
def serve(request, document_id, document_filename): Document = get_document_model() doc = get_object_or_404(Document, id=document_id) # We want to ensure that the document filename provided in the URL matches the one associated with the considered # document_id. If not we can't be sure that the document the user wants to access is the one corresponding to the # <document_id, document_filename> pair. if doc.filename != document_filename: raise Http404('This document does not match the given filename.') for fn in hooks.get_hooks('before_serve_document'): result = fn(doc, request) if isinstance(result, HttpResponse): return result # Send document_served signal document_served.send(sender=Document, instance=doc, request=request) try: local_path = doc.file.path except NotImplementedError: local_path = None if local_path: # Use tuiuiu.utils.sendfile to serve the file; # this provides support for mimetypes, if-modified-since and django-sendfile backends if hasattr(settings, 'SENDFILE_BACKEND'): return sendfile(request, local_path, attachment=True, attachment_filename=doc.filename) else: # Fallback to streaming backend if user hasn't specified SENDFILE_BACKEND return sendfile(request, local_path, attachment=True, attachment_filename=doc.filename, backend=sendfile_streaming_backend.sendfile) else: # We are using a storage backend which does not expose filesystem paths # (e.g. storages.backends.s3boto.S3BotoStorage). # Fall back on pre-sendfile behaviour of reading the file content and serving it # as a StreamingHttpResponse wrapper = FileWrapper(doc.file) response = StreamingHttpResponse( wrapper, content_type='application/octet-stream') try: response[ 'Content-Disposition'] = 'attachment; filename=%s' % doc.filename except BadHeaderError: # Unicode filenames can fail on Django <1.8, Python 2 due to # https://code.djangoproject.com/ticket/20889 - try with an ASCIIfied version of the name response[ 'Content-Disposition'] = 'attachment; filename=%s' % unidecode( doc.filename) # FIXME: storage backends are not guaranteed to implement 'size' response['Content-Length'] = doc.file.size return response
def __init__(self, request): self.request = request self.summary_items = [] for fn in hooks.get_hooks('construct_homepage_summary_items'): fn(request, self.summary_items)