Merge branch 'dadosch-django-v2'

This commit is contained in:
Daniel Quinn 2018-09-02 21:48:59 +01:00
commit 0868390d63
19 changed files with 72 additions and 56 deletions

View File

@ -40,7 +40,7 @@ Project maintainers who do not follow or enforce the Code of Conduct in good fai
## Attribution ## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4 to remove puritanical language. The original is available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org [homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/ [version]: http://contributor-covenant.org/version/1/4/

View File

@ -4,7 +4,7 @@ verify_ssl = true
name = "pypi" name = "pypi"
[packages] [packages]
django = "<2.0,>=1.11" django = "<2.1,>=2.0"
pillow = "*" pillow = "*"
coveralls = "*" coveralls = "*"
dateparser = "*" dateparser = "*"
@ -12,7 +12,6 @@ django-cors-headers = "*"
django-crispy-forms = "*" django-crispy-forms = "*"
django-extensions = "*" django-extensions = "*"
django-filter = "*" django-filter = "*"
django-flat-responsive = "*"
djangorestframework = "*" djangorestframework = "*"
factory-boy = "*" factory-boy = "*"
filemagic = "*" filemagic = "*"

15
Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "f38e72c2d07bd711cf7b3dd168e4fa39df3e8b86f790bda8c2c27a762c6f7447" "sha256": "e20c2294bcafd346ee57901df94a515a12976ed192dc37df848b39b56bdd1f4b"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": {}, "requires": {},
@ -106,11 +106,11 @@
}, },
"django": { "django": {
"hashes": [ "hashes": [
"sha256:8176ac7985fe6737ce3d6b2531b4a2453cb7c3377c9db00bacb2b3320f4a1311", "sha256:0c5b65847d00845ee404bbc0b4a85686f15eb3001ffddda3db4e9baa265bf136",
"sha256:b18235d82426f09733d2de9910cee975cf52ff05e5f836681eb957d105a05a40" "sha256:68aeea369a8130259354b6ba1fa9babe0c5ee6bced505dea4afcd00f765ae38b"
], ],
"index": "pypi", "index": "pypi",
"version": "==1.11.15" "version": "==2.0.8"
}, },
"django-cors-headers": { "django-cors-headers": {
"hashes": [ "hashes": [
@ -144,13 +144,6 @@
"index": "pypi", "index": "pypi",
"version": "==2.0.0" "version": "==2.0.0"
}, },
"django-flat-responsive": {
"hashes": [
"sha256:451caa2700c541b52fb7ce2d34d3d8dee9e980cf29f5463bc8a8c6256a1a6474"
],
"index": "pypi",
"version": "==2.0"
},
"djangorestframework": { "djangorestframework": {
"hashes": [ "hashes": [
"sha256:b6714c3e4b0f8d524f193c91ecf5f5450092c2145439ac2769711f7eba89a9d9", "sha256:b6714c3e4b0f8d524f193c91ecf5f5450092c2145439ac2769711f7eba89a9d9",

View File

@ -1,6 +1,17 @@
Changelog Changelog
######### #########
2.2.0
=====
* Thanks to `dadosch`_ and `Wolfgang Mader`_, this is the first version of
Paperless that supports Django 2.0! As a result of their hard work, you can
now also run Paperless on Python 3.7 as well: `#386`_ & `#390`_.
* `Stéphane Brunner`_ added a few lines of code that made tagging interface a lot
easier on those of us with lots of different tags: `#391`_.
* `Kilian Koeltzsch`_ noticed a bug in how we capture & automatically create
tags, so that's fixed now too: `#384`_.
2.1.0 2.1.0
===== =====
@ -451,6 +462,10 @@ bulk of the work on this big change.
.. _mcronce: https://github.com/mcronce .. _mcronce: https://github.com/mcronce
.. _Enno Lohmeier: https://github.com/elohmeier .. _Enno Lohmeier: https://github.com/elohmeier
.. _Mark McFate: https://github.com/SummittDweller .. _Mark McFate: https://github.com/SummittDweller
.. _dadosch: https://github.com/dadosch
.. _Wolfgang Mader: https://github.com/wmader
.. _Stéphane Brunner: https://github.com/sbrunner
.. _Kilian Koeltzsch: https://github.com/kiliankoe
.. _#20: https://github.com/danielquinn/paperless/issues/20 .. _#20: https://github.com/danielquinn/paperless/issues/20
.. _#44: https://github.com/danielquinn/paperless/issues/44 .. _#44: https://github.com/danielquinn/paperless/issues/44
@ -525,6 +540,10 @@ bulk of the work on this big change.
.. _#374: https://github.com/danielquinn/paperless/pull/374 .. _#374: https://github.com/danielquinn/paperless/pull/374
.. _#375: https://github.com/danielquinn/paperless/pull/375 .. _#375: https://github.com/danielquinn/paperless/pull/375
.. _#376: https://github.com/danielquinn/paperless/pull/376 .. _#376: https://github.com/danielquinn/paperless/pull/376
.. _#384: https://github.com/danielquinn/paperless/issues/384
.. _#386: https://github.com/danielquinn/paperless/issues/386
.. _#391: https://github.com/danielquinn/paperless/pull/391
.. _#390: https://github.com/danielquinn/paperless/pull/390
.. _pipenv: https://docs.pipenv.org/ .. _pipenv: https://docs.pipenv.org/
.. _a new home on Docker Hub: https://hub.docker.com/r/danielquinn/paperless/ .. _a new home on Docker Hub: https://hub.docker.com/r/danielquinn/paperless/

View File

@ -11,8 +11,7 @@ django-cors-headers==2.4.0
django-crispy-forms==1.7.2 django-crispy-forms==1.7.2
django-extensions==2.1.2 django-extensions==2.1.2
django-filter==2.0.0 django-filter==2.0.0
django-flat-responsive==2.0 django==2.0.8
django==1.11.15
djangorestframework==3.8.2 djangorestframework==3.8.2
docopt==0.6.2 docopt==0.6.2
execnet==1.5.0; python_version != '3.1.*' execnet==1.5.0; python_version != '3.1.*'

View File

@ -3,8 +3,13 @@ from datetime import datetime
from django.conf import settings from django.conf import settings
from django.contrib import admin from django.contrib import admin
from django.contrib.auth.models import User, Group from django.contrib.auth.models import User, Group
from django.core.urlresolvers import reverse try:
from django.core.urlresolvers import reverse
except ImportError:
from django.urls import reverse
from django.templatetags.static import static from django.templatetags.static import static
from django.utils.safestring import mark_safe
from django.utils.html import format_html, format_html_join
from .models import Correspondent, Tag, Document, Log from .models import Correspondent, Tag, Document, Log
@ -178,7 +183,7 @@ class DocumentAdmin(CommonAdmin):
) )
} }
) )
return r return mark_safe(r)
tags_.allow_tags = True tags_.allow_tags = True
def document(self, obj): def document(self, obj):
@ -198,16 +203,13 @@ class DocumentAdmin(CommonAdmin):
@staticmethod @staticmethod
def _html_tag(kind, inside=None, **kwargs): def _html_tag(kind, inside=None, **kwargs):
attributes = format_html_join(' ', '{}="{}"', kwargs.items())
attributes = []
for lft, rgt in kwargs.items():
attributes.append('{}="{}"'.format(lft, rgt))
if inside is not None: if inside is not None:
return "<{kind} {attributes}>{inside}</{kind}>".format( return format_html("<{kind} {attributes}>{inside}</{kind}>",
kind=kind, attributes=" ".join(attributes), inside=inside) kind=kind, attributes=attributes, inside=inside)
return "<{} {}/>".format(kind, " ".join(attributes)) return format_html("<{} {}/>", kind, attributes)
class LogAdmin(CommonAdmin): class LogAdmin(CommonAdmin):

View File

@ -5,7 +5,7 @@ from .models import Correspondent, Document, Tag
class CorrespondentFilterSet(FilterSet): class CorrespondentFilterSet(FilterSet):
class Meta(object): class Meta:
model = Correspondent model = Correspondent
fields = { fields = {
"name": [ "name": [
@ -18,7 +18,7 @@ class CorrespondentFilterSet(FilterSet):
class TagFilterSet(FilterSet): class TagFilterSet(FilterSet):
class Meta(object): class Meta:
model = Tag model = Tag
fields = { fields = {
"name": [ "name": [
@ -42,15 +42,18 @@ class DocumentFilterSet(FilterSet):
) )
} }
correspondent__name = CharFilter(name="correspondent__name", **CHAR_KWARGS) correspondent__name = CharFilter(
correspondent__slug = CharFilter(name="correspondent__slug", **CHAR_KWARGS) field_name="correspondent__name", **CHAR_KWARGS)
tags__name = CharFilter(name="tags__name", **CHAR_KWARGS) correspondent__slug = CharFilter(
tags__slug = CharFilter(name="tags__slug", **CHAR_KWARGS) field_name="correspondent__slug", **CHAR_KWARGS)
tags__empty = BooleanFilter(name='tags', tags__name = CharFilter(
lookup_expr='isnull', field_name="tags__name", **CHAR_KWARGS)
distinct=True) tags__slug = CharFilter(
field_name="tags__slug", **CHAR_KWARGS)
tags__empty = BooleanFilter(
field_name="tags", lookup_expr="isnull", distinct=True)
class Meta(object): class Meta:
model = Document model = Document
fields = { fields = {
"title": [ "title": [

View File

@ -32,7 +32,6 @@ def realign_senders(apps, schema_editor):
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('documents', '0002_auto_20151226_1316'), ('documents', '0002_auto_20151226_1316'),
] ]

View File

@ -6,7 +6,7 @@ from django.db import migrations
class Migration(migrations.Migration): class Migration(migrations.Migration):
atomic = False
dependencies = [ dependencies = [
('documents', '0010_log'), ('documents', '0010_log'),
] ]

View File

@ -112,7 +112,6 @@ def move_documents_and_create_thumbnails(apps, schema_editor):
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('documents', '0011_auto_20160303_1929'), ('documents', '0011_auto_20160303_1929'),
] ]

View File

@ -128,7 +128,6 @@ def do_nothing(apps, schema_editor):
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('documents', '0013_auto_20160325_2111'), ('documents', '0013_auto_20160325_2111'),
] ]

View File

@ -15,7 +15,6 @@ def reverse_func(apps, schema_editor):
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('documents', '0018_auto_20170715_1712'), ('documents', '0018_auto_20170715_1712'),
] ]

View File

@ -11,8 +11,8 @@ def set_added_time_to_created_time(apps, schema_editor):
doc.added = doc.created doc.added = doc.created
doc.save() doc.save()
class Migration(migrations.Migration):
class Migration(migrations.Migration):
dependencies = [ dependencies = [
('documents', '0019_add_consumer_user'), ('documents', '0019_add_consumer_user'),
] ]

View File

@ -10,7 +10,10 @@ from collections import OrderedDict
from fuzzywuzzy import fuzz from fuzzywuzzy import fuzz
from django.conf import settings from django.conf import settings
from django.core.urlresolvers import reverse try:
from django.core.urlresolvers import reverse
except ImportError:
from django.urls import reverse
from django.db import models 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

View File

@ -5,14 +5,14 @@ from .models import Correspondent, Tag, Document, Log
class CorrespondentSerializer(serializers.HyperlinkedModelSerializer): class CorrespondentSerializer(serializers.HyperlinkedModelSerializer):
class Meta(object): class Meta:
model = Correspondent model = Correspondent
fields = ("id", "slug", "name") fields = ("id", "slug", "name")
class TagSerializer(serializers.HyperlinkedModelSerializer): class TagSerializer(serializers.HyperlinkedModelSerializer):
class Meta(object): class Meta:
model = Tag model = Tag
fields = ( fields = (
"id", "slug", "name", "colour", "match", "matching_algorithm") "id", "slug", "name", "colour", "match", "matching_algorithm")
@ -34,7 +34,7 @@ class DocumentSerializer(serializers.ModelSerializer):
view_name="drf:correspondent-detail", allow_null=True) view_name="drf:correspondent-detail", allow_null=True)
tags = TagsField(view_name="drf:tag-detail", many=True) tags = TagsField(view_name="drf:tag-detail", many=True)
class Meta(object): class Meta:
model = Document model = Document
fields = ( fields = (
"id", "id",
@ -57,7 +57,7 @@ class LogSerializer(serializers.ModelSerializer):
time = serializers.DateTimeField() time = serializers.DateTimeField()
messages = serializers.CharField() messages = serializers.CharField()
class Meta(object): class Meta:
model = Log model = Log
fields = ( fields = (
"time", "time",

View File

@ -68,7 +68,6 @@ INSTALLED_APPS = [
"reminders.apps.RemindersConfig", "reminders.apps.RemindersConfig",
"paperless_tesseract.apps.PaperlessTesseractConfig", "paperless_tesseract.apps.PaperlessTesseractConfig",
"flat_responsive", # TODO: Remove as of Django 2.x
"django.contrib.admin", "django.contrib.admin",
"rest_framework", "rest_framework",
@ -82,14 +81,13 @@ if os.getenv("PAPERLESS_INSTALLED_APPS"):
MIDDLEWARE_CLASSES = [ MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware', 'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',
] ]
@ -99,9 +97,9 @@ CORS_ORIGIN_WHITELIST = tuple(os.getenv("PAPERLESS_CORS_ALLOWED_HOSTS", "localho
# 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")):
_index = MIDDLEWARE_CLASSES.index("django.contrib.auth.middleware.AuthenticationMiddleware") _index = MIDDLEWARE.index("django.contrib.auth.middleware.AuthenticationMiddleware")
MIDDLEWARE_CLASSES[_index] = "paperless.middleware.Middleware" MIDDLEWARE[_index] = "paperless.middleware.Middleware"
MIDDLEWARE_CLASSES.remove("django.contrib.auth.middleware.SessionAuthenticationMiddleware") MIDDLEWARE.remove("django.contrib.auth.middleware.SessionAuthenticationMiddleware")
ROOT_URLCONF = 'paperless.urls' ROOT_URLCONF = 'paperless.urls'

View File

@ -28,9 +28,11 @@ urlpatterns = [
# API # API
url( url(
r"^api/auth/", r"^api/auth/",
include('rest_framework.urls', namespace="rest_framework") include(
('rest_framework.urls', 'rest_framework'),
namespace="rest_framework")
), ),
url(r"^api/", include(router.urls, namespace="drf")), url(r"^api/", include((router.urls, 'drf'), namespace="drf")),
# File downloads # File downloads
url( url(

View File

@ -1 +1 @@
__version__ = (2, 1, 0) __version__ = (2, 2, 0)

View File

@ -3,6 +3,8 @@ from django.db import models
class Reminder(models.Model): class Reminder(models.Model):
document = models.ForeignKey("documents.Document") document = models.ForeignKey(
"documents.Document", on_delete=models.PROTECT
)
date = models.DateTimeField() date = models.DateTimeField()
note = models.TextField(blank=True) note = models.TextField(blank=True)