def test_filtering_tags(self): get_document_model().objects.get(id=3).tags.add('test') response = self.get_response(tags='test') content = json.loads(response.content.decode('UTF-8')) document_id_list = self.get_document_id_list(content) self.assertEqual(document_id_list, [3])
def test_tags(self): get_document_model().objects.get(id=1).tags.add('hello') get_document_model().objects.get(id=1).tags.add('world') response = self.get_response(1) content = json.loads(response.content.decode('UTF-8')) self.assertIn('tags', content['meta']) self.assertEqual(content['meta']['tags'], ['hello', 'world'])
def test_offset_total_count(self): response = self.get_response(offset=10) content = json.loads(response.content.decode('UTF-8')) # The total count must not be affected by "offset" self.assertEqual(content['meta']['total_count'], get_document_model().objects.count())
def add(request): Document = get_document_model() DocumentForm = get_document_form(Document) if request.method == 'POST': doc = Document(uploaded_by_user=request.user) form = DocumentForm(request.POST, request.FILES, instance=doc, user=request.user) if form.is_valid(): form.save() # Reindex the document to make sure all tags are indexed search_index.insert_or_update_object(doc) messages.success(request, _("Document '{0}' added.").format(doc.title), buttons=[ messages.button( reverse('tuiuiudocs:edit', args=(doc.id, )), _('Edit')) ]) return redirect('tuiuiudocs:index') else: messages.error(request, _("The document could not be saved due to errors.")) else: form = DocumentForm(user=request.user) return render(request, "tuiuiudocs/documents/add.html", { 'form': form, })
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 chooser_upload(request): Document = get_document_model() DocumentForm = get_document_form(Document) if request.method == 'POST': document = Document(uploaded_by_user=request.user) form = DocumentForm(request.POST, request.FILES, instance=document, user=request.user) if form.is_valid(): form.save() # Reindex the document to make sure all tags are indexed search_index.insert_or_update_object(document) return render_modal_workflow( request, None, 'tuiuiudocs/chooser/document_chosen.js', {'document_json': get_document_json(document)}) else: form = DocumentForm(user=request.user) documents = Document.objects.order_by('title') return render_modal_workflow(request, 'tuiuiudocs/chooser/chooser.html', 'tuiuiudocs/chooser/chooser.js', { 'documents': documents, 'uploadform': form })
def usage(request, document_id): Document = get_document_model() doc = get_object_or_404(Document, id=document_id) paginator, used_by = paginate(request, doc.get_usage()) return render(request, "tuiuiudocs/documents/usage.html", { 'document': doc, 'used_by': used_by })
def unregister_signal_handlers(): Image = get_image_model() Document = get_document_model() for model in get_page_models(): page_published.disconnect(purge_page_from_cache, sender=model) page_unpublished.disconnect(purge_page_from_cache, sender=model) post_save.disconnect(purge_image_from_cache, sender=Image) post_delete.disconnect(purge_image_from_cache, sender=Image) post_save.disconnect(purge_document_from_cache, sender=Document) post_delete.disconnect(purge_document_from_cache, sender=Document)
def expand_db_attributes(attrs, for_editor): Document = get_document_model() try: doc = Document.objects.get(id=attrs['id']) if for_editor: editor_attrs = 'data-linktype="document" data-id="%d" ' % doc.id else: editor_attrs = '' return '<a %shref="%s">' % (editor_attrs, escape(doc.url)) except Document.DoesNotExist: return "<a>"
def describe_collection_docs(collection): docs_count = get_document_model().objects.filter( collection=collection).count() if docs_count: url = urlresolvers.reverse('tuiuiudocs:index') + ('?collection_id=%d' % collection.id) return { 'count': docs_count, 'count_text': ungettext("%(count)s document", "%(count)s documents", docs_count) % { 'count': docs_count }, 'url': url, }
def delete(request, document_id): Document = get_document_model() doc = get_object_or_404(Document, id=document_id) if not permission_policy.user_has_permission_for_instance( request.user, 'delete', doc): return permission_denied(request) if request.method == 'POST': doc.delete() messages.success(request, _("Document '{0}' deleted.").format(doc.title)) return redirect('tuiuiudocs:index') return render(request, "tuiuiudocs/documents/confirm_delete.html", { 'document': doc, })
def test_basic(self): response = self.get_response() self.assertEqual(response.status_code, 200) self.assertEqual(response['Content-type'], 'application/json') # Will crash if the JSON is invalid content = json.loads(response.content.decode('UTF-8')) # Check that the meta section is there self.assertIn('meta', content) self.assertIsInstance(content['meta'], dict) # Check that the total count is there and correct self.assertIn('total_count', content['meta']) self.assertIsInstance(content['meta']['total_count'], int) self.assertEqual(content['meta']['total_count'], get_document_model().objects.count()) # Check that the items section is there self.assertIn('items', content) self.assertIsInstance(content['items'], list) # Check that each document has a meta section with type and detail_url attributes for document in content['items']: self.assertIn('meta', document) self.assertIsInstance(document['meta'], dict) self.assertEqual(set(document['meta'].keys()), {'type', 'detail_url', 'download_url', 'tags'}) # Type should always be tuiuiudocs.Document self.assertEqual(document['meta']['type'], 'tuiuiudocs.Document') # Check detail_url self.assertEqual( document['meta']['detail_url'], 'http://localhost/api/v2beta/documents/%d/' % document['id']) # Check download_url self.assertTrue(document['meta']['download_url'].startswith( 'http://localhost/documents/%d/' % document['id']))
def get_context(self): return { 'total_docs': get_document_model().objects.count(), }
class DocumentsAPIEndpoint(BaseAPIEndpoint): base_serializer_class = DocumentSerializer filter_backends = [FieldsFilter, OrderingFilter, SearchFilter] extra_api_fields = ['title', 'tags'] name = 'documents' model = get_document_model()
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 test_delete_document_purges(self, purge): get_document_model().objects.get(id=5).delete() purge.assert_any_call('http://api.example.com/api/v2beta/documents/5/')
def edit(request, document_id): Document = get_document_model() DocumentForm = get_document_form(Document) doc = get_object_or_404(Document, id=document_id) if not permission_policy.user_has_permission_for_instance( request.user, 'change', doc): return permission_denied(request) if request.method == 'POST': original_file = doc.file form = DocumentForm(request.POST, request.FILES, instance=doc, user=request.user) if form.is_valid(): if 'file' in form.changed_data: # if providing a new document file, delete the old one. # NB Doing this via original_file.delete() clears the file field, # which definitely isn't what we want... original_file.storage.delete(original_file.name) doc = form.save() # Reindex the document to make sure all tags are indexed search_index.insert_or_update_object(doc) messages.success(request, _("Document '{0}' updated").format(doc.title), buttons=[ messages.button( reverse('tuiuiudocs:edit', args=(doc.id, )), _('Edit')) ]) return redirect('tuiuiudocs:index') else: messages.error(request, _("The document could not be saved due to errors.")) else: form = DocumentForm(instance=doc, user=request.user) filesize = None # Get file size when there is a file associated with the Document object if doc.file: try: filesize = doc.file.size except OSError: # File doesn't exist pass if not filesize: messages.error( request, _("The file could not be found. Please change the source or delete the document" ), buttons=[ messages.button(reverse('tuiuiudocs:delete', args=(doc.id, )), _('Delete')) ]) return render( request, "tuiuiudocs/documents/edit.html", { 'document': doc, 'filesize': filesize, 'form': form, 'user_can_delete': permission_policy.user_has_permission_for_instance( request.user, 'delete', doc), })
def index(request): Document = get_document_model() # Get documents (filtered by user permission) documents = permission_policy.instances_user_has_any_permission_for( request.user, ['change', 'delete']) # Ordering if 'ordering' in request.GET and request.GET['ordering'] in [ 'title', '-created_at' ]: ordering = request.GET['ordering'] else: ordering = '-created_at' documents = documents.order_by(ordering) # Filter by collection current_collection = None collection_id = request.GET.get('collection_id') if collection_id: try: current_collection = Collection.objects.get(id=collection_id) documents = documents.filter(collection=current_collection) except (ValueError, Collection.DoesNotExist): pass # Search query_string = None if 'q' in request.GET: form = SearchForm(request.GET, placeholder=_("Search documents")) if form.is_valid(): query_string = form.cleaned_data['q'] documents = documents.search(query_string) else: form = SearchForm(placeholder=_("Search documents")) # Pagination paginator, documents = paginate(request, documents) collections = permission_policy.collections_user_has_any_permission_for( request.user, ['add', 'change']) if len(collections) < 2: collections = None # Create response if request.is_ajax(): return render( request, 'tuiuiudocs/documents/results.html', { 'ordering': ordering, 'documents': documents, 'query_string': query_string, 'is_searching': bool(query_string), }) else: return render( request, 'tuiuiudocs/documents/index.html', { 'ordering': ordering, 'documents': documents, 'query_string': query_string, 'is_searching': bool(query_string), 'search_form': form, 'popular_tags': popular_tags_for_model(Document), 'user_can_add': permission_policy.user_has_permission(request.user, 'add'), 'collections': collections, 'current_collection': current_collection, })
def document_chosen(request, document_id): document = get_object_or_404(get_document_model(), id=document_id) return render_modal_workflow( request, None, 'tuiuiudocs/chooser/document_chosen.js', {'document_json': get_document_json(document)})
from __future__ import absolute_import, unicode_literals from tuiuiu.tuiuiucore.permission_policies.collections import CollectionOwnershipPermissionPolicy from tuiuiu.tuiuiudocs.models import Document, get_document_model permission_policy = CollectionOwnershipPermissionPolicy( get_document_model(), auth_model=Document, owner_field_name='uploaded_by_user' )
def target_model(self): from tuiuiu.tuiuiudocs.models import get_document_model return get_document_model()
def __init__(self, **kwargs): super(AdminDocumentChooser, self).__init__(**kwargs) self.document_model = get_document_model()