mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	removed reminders, changed a bunch of stuff
This commit is contained in:
		| @@ -1,17 +1,11 @@ | |||||||
| from datetime import datetime, timedelta | from datetime import datetime | ||||||
|  |  | ||||||
| from django.conf import settings | from django.conf import settings | ||||||
| from django.contrib import admin, messages | from django.contrib import admin | ||||||
| from django.contrib.admin.templatetags.admin_urls import add_preserved_filters |  | ||||||
| from django.contrib.auth.models import Group, User | from django.contrib.auth.models import Group, User | ||||||
| from django.db import models | from django.db import models | ||||||
| from django.http import HttpResponseRedirect |  | ||||||
| from django.templatetags.static import static |  | ||||||
| from django.urls import reverse |  | ||||||
| from django.utils.html import format_html, format_html_join | from django.utils.html import format_html, format_html_join | ||||||
| from django.utils.http import urlquote |  | ||||||
| from django.utils.safestring import mark_safe | from django.utils.safestring import mark_safe | ||||||
| from djangoql.admin import DjangoQLSearchMixin |  | ||||||
|  |  | ||||||
| from .models import Correspondent, Document, DocumentType, Log, Tag | from .models import Correspondent, Document, DocumentType, Log, Tag | ||||||
|  |  | ||||||
| @@ -156,12 +150,7 @@ class DocumentTypeAdmin(CommonAdmin): | |||||||
|     document_count.admin_order_field = "document_count" |     document_count.admin_order_field = "document_count" | ||||||
|  |  | ||||||
|  |  | ||||||
| class DocumentAdmin(DjangoQLSearchMixin, CommonAdmin): | class DocumentAdmin(CommonAdmin): | ||||||
|  |  | ||||||
|     class Media: |  | ||||||
|         css = { |  | ||||||
|             "all": ("paperless.css",) |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     search_fields = ("correspondent__name", "title", "content", "tags__name") |     search_fields = ("correspondent__name", "title", "content", "tags__name") | ||||||
|     readonly_fields = ("added", "file_type", "storage_type",) |     readonly_fields = ("added", "file_type", "storage_type",) | ||||||
| @@ -187,20 +176,6 @@ class DocumentAdmin(DjangoQLSearchMixin, CommonAdmin): | |||||||
|         return obj.created.date().strftime("%Y-%m-%d") |         return obj.created.date().strftime("%Y-%m-%d") | ||||||
|     created_.short_description = "Created" |     created_.short_description = "Created" | ||||||
|  |  | ||||||
|     @mark_safe |  | ||||||
|     def thumbnail(self, obj): |  | ||||||
|         return self._html_tag( |  | ||||||
|             "a", |  | ||||||
|             self._html_tag( |  | ||||||
|                 "img", |  | ||||||
|                 src=reverse("fetch", kwargs={"kind": "thumb", "pk": obj.pk}), |  | ||||||
|                 height=100, |  | ||||||
|                 alt="Thumbnail of {}".format(obj.file_name), |  | ||||||
|                 title=obj.file_name |  | ||||||
|             ), |  | ||||||
|             href=obj.download_url |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     @mark_safe |     @mark_safe | ||||||
|     def tags_(self, obj): |     def tags_(self, obj): | ||||||
|         r = "" |         r = "" | ||||||
| @@ -212,22 +187,6 @@ class DocumentAdmin(DjangoQLSearchMixin, CommonAdmin): | |||||||
|             ) |             ) | ||||||
|         return r |         return r | ||||||
|  |  | ||||||
|     @mark_safe |  | ||||||
|     def document(self, obj): |  | ||||||
|         # TODO: is this method even used anymore? |  | ||||||
|         return self._html_tag( |  | ||||||
|             "a", |  | ||||||
|             self._html_tag( |  | ||||||
|                 "img", |  | ||||||
|                 src=static("documents/img/{}.png".format(obj.file_type)), |  | ||||||
|                 width=22, |  | ||||||
|                 height=22, |  | ||||||
|                 alt=obj.file_type, |  | ||||||
|                 title=obj.file_name |  | ||||||
|             ), |  | ||||||
|             href=obj.download_url |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def _html_tag(kind, inside=None, **kwargs): |     def _html_tag(kind, inside=None, **kwargs): | ||||||
|         attributes = format_html_join(' ', '{}="{}"', kwargs.items()) |         attributes = format_html_join(' ', '{}="{}"', kwargs.items()) | ||||||
| @@ -253,5 +212,5 @@ admin.site.register(Log, LogAdmin) | |||||||
|  |  | ||||||
|  |  | ||||||
| # Unless we implement multi-user, these default registrations don't make sense. | # Unless we implement multi-user, these default registrations don't make sense. | ||||||
| #admin.site.unregister(Group) | admin.site.unregister(Group) | ||||||
| #admin.site.unregister(User) | admin.site.unregister(User) | ||||||
|   | |||||||
| @@ -13,7 +13,6 @@ from django.db import models | |||||||
| from django.template.defaultfilters import slugify | from django.template.defaultfilters import slugify | ||||||
| from django.utils import timezone | from django.utils import timezone | ||||||
| from django.utils.text import slugify | from django.utils.text import slugify | ||||||
| from fuzzywuzzy import fuzz |  | ||||||
| from collections import defaultdict | from collections import defaultdict | ||||||
|  |  | ||||||
| from .managers import LogManager | from .managers import LogManager | ||||||
|   | |||||||
| @@ -36,21 +36,22 @@ class TagSerializer(serializers.HyperlinkedModelSerializer): | |||||||
|             "slug", |             "slug", | ||||||
|             "name", |             "name", | ||||||
|             "colour", |             "colour", | ||||||
|             "automatic_classification" |             "automatic_classification", | ||||||
|  |             "is_inbox_tag" | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|  |  | ||||||
| class CorrespondentField(serializers.HyperlinkedRelatedField): | class CorrespondentField(serializers.PrimaryKeyRelatedField): | ||||||
|     def get_queryset(self): |     def get_queryset(self): | ||||||
|         return Correspondent.objects.all() |         return Correspondent.objects.all() | ||||||
|  |  | ||||||
|  |  | ||||||
| class TagsField(serializers.HyperlinkedRelatedField): | class TagsField(serializers.PrimaryKeyRelatedField): | ||||||
|     def get_queryset(self): |     def get_queryset(self): | ||||||
|         return Tag.objects.all() |         return Tag.objects.all() | ||||||
|  |  | ||||||
|  |  | ||||||
| class DocumentTypeField(serializers.HyperlinkedRelatedField): | class DocumentTypeField(serializers.PrimaryKeyRelatedField): | ||||||
|     def get_queryset(self): |     def get_queryset(self): | ||||||
|         return DocumentType.objects.all() |         return DocumentType.objects.all() | ||||||
|  |  | ||||||
| @@ -58,10 +59,10 @@ class DocumentTypeField(serializers.HyperlinkedRelatedField): | |||||||
| class DocumentSerializer(serializers.ModelSerializer): | class DocumentSerializer(serializers.ModelSerializer): | ||||||
|  |  | ||||||
|     correspondent = CorrespondentField( |     correspondent = CorrespondentField( | ||||||
|         view_name="drf:correspondent-detail", allow_null=True) |         allow_null=True) | ||||||
|     tags = TagsField(view_name="drf:tag-detail", many=True) |     tags = TagsField(many=True) | ||||||
|     document_type = DocumentTypeField( |     document_type = DocumentTypeField( | ||||||
|         view_name="drf:documenttype-detail", allow_null=True) |         allow_null=True) | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|         model = Document |         model = Document | ||||||
| @@ -80,6 +81,7 @@ class DocumentSerializer(serializers.ModelSerializer): | |||||||
|             "file_name", |             "file_name", | ||||||
|             "download_url", |             "download_url", | ||||||
|             "thumbnail_url", |             "thumbnail_url", | ||||||
|  |             "archive_serial_number" | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,61 +0,0 @@ | |||||||
| from random import randint |  | ||||||
|  |  | ||||||
| from django.contrib.admin.models import LogEntry |  | ||||||
| from django.contrib.auth.models import User |  | ||||||
| from django.test import TestCase, override_settings |  | ||||||
|  |  | ||||||
| from ..models import Correspondent, Document, Tag |  | ||||||
| from ..signals import document_consumption_finished |  | ||||||
|  |  | ||||||
| @override_settings(POST_CONSUME_SCRIPT=None) |  | ||||||
| class TestDocumentConsumptionFinishedSignal(TestCase): |  | ||||||
|     """ |  | ||||||
|     We make use of document_consumption_finished, so we should test that it's |  | ||||||
|     doing what we expect wrt to tag & correspondent matching. |  | ||||||
|     """ |  | ||||||
|  |  | ||||||
|     def setUp(self): |  | ||||||
|         TestCase.setUp(self) |  | ||||||
|         User.objects.create_user(username='test_consumer', password='12345') |  | ||||||
|         self.doc_contains = Document.objects.create( |  | ||||||
|             content="I contain the keyword.", file_type="pdf") |  | ||||||
|  |  | ||||||
|     def test_tag_applied_any(self): |  | ||||||
|         t1 = Tag.objects.create( |  | ||||||
|             name="test", match="keyword", matching_algorithm=Tag.MATCH_ANY) |  | ||||||
|         document_consumption_finished.send( |  | ||||||
|             sender=self.__class__, document=self.doc_contains) |  | ||||||
|         self.assertTrue(list(self.doc_contains.tags.all()) == [t1]) |  | ||||||
|  |  | ||||||
|     def test_tag_not_applied(self): |  | ||||||
|         Tag.objects.create( |  | ||||||
|             name="test", match="no-match", matching_algorithm=Tag.MATCH_ANY) |  | ||||||
|         document_consumption_finished.send( |  | ||||||
|             sender=self.__class__, document=self.doc_contains) |  | ||||||
|         self.assertTrue(list(self.doc_contains.tags.all()) == []) |  | ||||||
|  |  | ||||||
|     def test_correspondent_applied(self): |  | ||||||
|         correspondent = Correspondent.objects.create( |  | ||||||
|             name="test", |  | ||||||
|             match="keyword", |  | ||||||
|             matching_algorithm=Correspondent.MATCH_ANY |  | ||||||
|         ) |  | ||||||
|         document_consumption_finished.send( |  | ||||||
|             sender=self.__class__, document=self.doc_contains) |  | ||||||
|         self.assertTrue(self.doc_contains.correspondent == correspondent) |  | ||||||
|  |  | ||||||
|     def test_correspondent_not_applied(self): |  | ||||||
|         Tag.objects.create( |  | ||||||
|             name="test", |  | ||||||
|             match="no-match", |  | ||||||
|             matching_algorithm=Correspondent.MATCH_ANY |  | ||||||
|         ) |  | ||||||
|         document_consumption_finished.send( |  | ||||||
|             sender=self.__class__, document=self.doc_contains) |  | ||||||
|         self.assertEqual(self.doc_contains.correspondent, None) |  | ||||||
|  |  | ||||||
|     def test_logentry_created(self): |  | ||||||
|         document_consumption_finished.send( |  | ||||||
|             sender=self.__class__, document=self.doc_contains) |  | ||||||
|  |  | ||||||
|         self.assertEqual(LogEntry.objects.count(), 1) |  | ||||||
| @@ -66,8 +66,6 @@ FORCE_SCRIPT_NAME = os.getenv("PAPERLESS_FORCE_SCRIPT_NAME") | |||||||
| # Application definition | # Application definition | ||||||
|  |  | ||||||
| INSTALLED_APPS = [ | INSTALLED_APPS = [ | ||||||
|     "whitenoise.runserver_nostatic", |  | ||||||
|  |  | ||||||
|     "django.contrib.auth", |     "django.contrib.auth", | ||||||
|     "django.contrib.contenttypes", |     "django.contrib.contenttypes", | ||||||
|     "django.contrib.sessions", |     "django.contrib.sessions", | ||||||
| @@ -79,19 +77,25 @@ INSTALLED_APPS = [ | |||||||
|  |  | ||||||
|     "paperless", |     "paperless", | ||||||
|     "documents.apps.DocumentsConfig", |     "documents.apps.DocumentsConfig", | ||||||
|     "reminders.apps.RemindersConfig", |  | ||||||
|     "paperless_tesseract.apps.PaperlessTesseractConfig", |     "paperless_tesseract.apps.PaperlessTesseractConfig", | ||||||
|     "paperless_text.apps.PaperlessTextConfig", |     "paperless_text.apps.PaperlessTextConfig", | ||||||
|  |  | ||||||
|     "django.contrib.admin", |     "django.contrib.admin", | ||||||
|  |  | ||||||
|     "rest_framework", |     "rest_framework", | ||||||
|     "crispy_forms", |     "rest_framework.authtoken", | ||||||
|     "django_filters", |     "django_filters", | ||||||
|     "djangoql", |  | ||||||
|  |  | ||||||
| ] | ] | ||||||
|  |  | ||||||
|  | REST_FRAMEWORK = { | ||||||
|  |     'DEFAULT_AUTHENTICATION_CLASSES': [ | ||||||
|  |         'rest_framework.authentication.BasicAuthentication', | ||||||
|  |         'rest_framework.authentication.SessionAuthentication', | ||||||
|  |         'rest_framework.authentication.TokenAuthentication', | ||||||
|  |     ] | ||||||
|  | } | ||||||
|  |  | ||||||
| if os.getenv("PAPERLESS_INSTALLED_APPS"): | if os.getenv("PAPERLESS_INSTALLED_APPS"): | ||||||
|     INSTALLED_APPS += os.getenv("PAPERLESS_INSTALLED_APPS").split(",") |     INSTALLED_APPS += os.getenv("PAPERLESS_INSTALLED_APPS").split(",") | ||||||
|  |  | ||||||
| @@ -111,7 +115,7 @@ MIDDLEWARE = [ | |||||||
| STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' | STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' | ||||||
|  |  | ||||||
| # We allow CORS from localhost:8080 | # We allow CORS from localhost:8080 | ||||||
| CORS_ORIGIN_WHITELIST = tuple(os.getenv("PAPERLESS_CORS_ALLOWED_HOSTS", "http://localhost:8080,https://localhost:8080,localhost:4200").split(",")) | CORS_ORIGIN_WHITELIST = tuple(os.getenv("PAPERLESS_CORS_ALLOWED_HOSTS", "http://localhost:8080,https://localhost:8080,http://localhost:4200").split(",")) | ||||||
|  |  | ||||||
| # If auth is disabled, we just use our "bypass" authentication middleware | # If auth is disabled, we just use our "bypass" authentication middleware | ||||||
| if bool(os.getenv("PAPERLESS_DISABLE_LOGIN", "false").lower() in ("yes", "y", "1", "t", "true")): | if bool(os.getenv("PAPERLESS_DISABLE_LOGIN", "false").lower() in ("yes", "y", "1", "t", "true")): | ||||||
| @@ -339,11 +343,5 @@ FILENAME_PARSE_TRANSFORMS = [] | |||||||
| for t in json.loads(os.getenv("PAPERLESS_FILENAME_PARSE_TRANSFORMS", "[]")): | for t in json.loads(os.getenv("PAPERLESS_FILENAME_PARSE_TRANSFORMS", "[]")): | ||||||
|     FILENAME_PARSE_TRANSFORMS.append((re.compile(t["pattern"]), t["repl"])) |     FILENAME_PARSE_TRANSFORMS.append((re.compile(t["pattern"]), t["repl"])) | ||||||
|  |  | ||||||
| # Specify for how many years a correspondent is considered recent. Recent |  | ||||||
| # correspondents will be shown in a separate "Recent correspondents" filter as |  | ||||||
| # well. Set to 0 to disable this filter. |  | ||||||
| PAPERLESS_RECENT_CORRESPONDENT_YEARS = int(os.getenv( |  | ||||||
|     "PAPERLESS_RECENT_CORRESPONDENT_YEARS", 0)) |  | ||||||
|  |  | ||||||
| # Specify the filename format for out files | # Specify the filename format for out files | ||||||
| PAPERLESS_FILENAME_FORMAT = os.getenv("PAPERLESS_FILENAME_FORMAT") | PAPERLESS_FILENAME_FORMAT = os.getenv("PAPERLESS_FILENAME_FORMAT") | ||||||
|   | |||||||
| @@ -16,14 +16,12 @@ from documents.views import ( | |||||||
|     TagViewSet, |     TagViewSet, | ||||||
|     DocumentTypeViewSet |     DocumentTypeViewSet | ||||||
| ) | ) | ||||||
| from reminders.views import ReminderViewSet |  | ||||||
|  |  | ||||||
| router = DefaultRouter() | router = DefaultRouter() | ||||||
| router.register(r"correspondents", CorrespondentViewSet) | router.register(r"correspondents", CorrespondentViewSet) | ||||||
| router.register(r"document_types", DocumentTypeViewSet) | router.register(r"document_types", DocumentTypeViewSet) | ||||||
| router.register(r"documents", DocumentViewSet) | router.register(r"documents", DocumentViewSet) | ||||||
| router.register(r"logs", LogViewSet) | router.register(r"logs", LogViewSet) | ||||||
| router.register(r"reminders", ReminderViewSet) |  | ||||||
| router.register(r"tags", TagViewSet) | router.register(r"tags", TagViewSet) | ||||||
|  |  | ||||||
| urlpatterns = [ | urlpatterns = [ | ||||||
|   | |||||||
| @@ -1,20 +0,0 @@ | |||||||
| from django.conf import settings |  | ||||||
| from django.contrib import admin |  | ||||||
|  |  | ||||||
| from .models import Reminder |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class ReminderAdmin(admin.ModelAdmin): |  | ||||||
|  |  | ||||||
|     class Media: |  | ||||||
|         css = { |  | ||||||
|             "all": ("paperless.css",) |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     list_per_page = settings.PAPERLESS_LIST_PER_PAGE |  | ||||||
|     list_display = ("date", "document", "note") |  | ||||||
|     list_filter = ("date",) |  | ||||||
|     list_editable = ("note",) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| admin.site.register(Reminder, ReminderAdmin) |  | ||||||
| @@ -1,5 +0,0 @@ | |||||||
| from django.apps import AppConfig |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class RemindersConfig(AppConfig): |  | ||||||
|     name = "reminders" |  | ||||||
| @@ -1,14 +0,0 @@ | |||||||
| from django_filters.rest_framework import CharFilter, FilterSet |  | ||||||
|  |  | ||||||
| from .models import Reminder |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class ReminderFilterSet(FilterSet): |  | ||||||
|  |  | ||||||
|     class Meta(object): |  | ||||||
|         model = Reminder |  | ||||||
|         fields = { |  | ||||||
|             "document": ["exact"], |  | ||||||
|             "date": ["gt", "lt", "gte", "lte", "exact"], |  | ||||||
|             "note": ["istartswith", "iendswith", "icontains"] |  | ||||||
|         } |  | ||||||
| @@ -1,27 +0,0 @@ | |||||||
| # -*- coding: utf-8 -*- |  | ||||||
| # Generated by Django 1.10.5 on 2017-03-25 15:58 |  | ||||||
| from __future__ import unicode_literals |  | ||||||
|  |  | ||||||
| from django.db import migrations, models |  | ||||||
| import django.db.models.deletion |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class Migration(migrations.Migration): |  | ||||||
|  |  | ||||||
|     initial = True |  | ||||||
|  |  | ||||||
|     dependencies = [ |  | ||||||
|         ('documents', '0016_auto_20170325_1558'), |  | ||||||
|     ] |  | ||||||
|  |  | ||||||
|     operations = [ |  | ||||||
|         migrations.CreateModel( |  | ||||||
|             name='Reminder', |  | ||||||
|             fields=[ |  | ||||||
|                 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |  | ||||||
|                 ('date', models.DateTimeField()), |  | ||||||
|                 ('note', models.TextField(blank=True)), |  | ||||||
|                 ('document', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='documents.Document')), |  | ||||||
|             ], |  | ||||||
|         ), |  | ||||||
|     ] |  | ||||||
| @@ -1,19 +0,0 @@ | |||||||
| # Generated by Django 2.0.8 on 2018-10-07 14:20 |  | ||||||
|  |  | ||||||
| from django.db import migrations, models |  | ||||||
| import django.db.models.deletion |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class Migration(migrations.Migration): |  | ||||||
|  |  | ||||||
|     dependencies = [ |  | ||||||
|         ('reminders', '0001_initial'), |  | ||||||
|     ] |  | ||||||
|  |  | ||||||
|     operations = [ |  | ||||||
|         migrations.AlterField( |  | ||||||
|             model_name='reminder', |  | ||||||
|             name='document', |  | ||||||
|             field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='documents.Document'), |  | ||||||
|         ), |  | ||||||
|     ] |  | ||||||
| @@ -1,9 +0,0 @@ | |||||||
| from django.db import models |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class Reminder(models.Model): |  | ||||||
|  |  | ||||||
|     document = models.ForeignKey( |  | ||||||
|         "documents.Document", on_delete=models.PROTECT) |  | ||||||
|     date = models.DateTimeField() |  | ||||||
|     note = models.TextField(blank=True) |  | ||||||
| @@ -1,14 +0,0 @@ | |||||||
| from documents.models import Document |  | ||||||
| from rest_framework import serializers |  | ||||||
|  |  | ||||||
| from .models import Reminder |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class ReminderSerializer(serializers.HyperlinkedModelSerializer): |  | ||||||
|  |  | ||||||
|     document = serializers.HyperlinkedRelatedField( |  | ||||||
|         view_name="drf:document-detail", queryset=Document.objects) |  | ||||||
|  |  | ||||||
|     class Meta(object): |  | ||||||
|         model = Reminder |  | ||||||
|         fields = ("id", "document", "date", "note") |  | ||||||
| @@ -1,3 +0,0 @@ | |||||||
| from django.test import TestCase |  | ||||||
|  |  | ||||||
| # Create your tests here. |  | ||||||
| @@ -1,22 +0,0 @@ | |||||||
| from django_filters.rest_framework import DjangoFilterBackend |  | ||||||
| from rest_framework.filters import OrderingFilter |  | ||||||
| from rest_framework.permissions import IsAuthenticated |  | ||||||
| from rest_framework.viewsets import ( |  | ||||||
|     ModelViewSet, |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| from .filters import ReminderFilterSet |  | ||||||
| from .models import Reminder |  | ||||||
| from .serialisers import ReminderSerializer |  | ||||||
| from paperless.views import StandardPagination |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class ReminderViewSet(ModelViewSet): |  | ||||||
|     model = Reminder |  | ||||||
|     queryset = Reminder.objects |  | ||||||
|     serializer_class = ReminderSerializer |  | ||||||
|     pagination_class = StandardPagination |  | ||||||
|     permission_classes = (IsAuthenticated,) |  | ||||||
|     filter_backends = (DjangoFilterBackend, OrderingFilter) |  | ||||||
|     filter_class = ReminderFilterSet |  | ||||||
|     ordering_fields = ("date", "document") |  | ||||||
		Reference in New Issue
	
	Block a user
	 Jonas Winkler
					Jonas Winkler