From: Radek Czajka Date: Wed, 2 Oct 2019 10:37:28 +0000 (+0200) Subject: Django 2.0 X-Git-Url: https://git.mdrn.pl/redakcja.git/commitdiff_plain/edf56edfdbea88b0e18c2e5aecbb6e62250ec3d7?ds=sidebyside Django 2.0 --- diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 08a8823b..9e27efad 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -11,7 +11,7 @@ python-slugify librarian==1.7.6 ## Django -Django==1.11.25 +Django==2.0.13 fnpdjango==0.4.3 django-pipeline==1.6.14 django-cas-ng==3.6.0 @@ -21,4 +21,4 @@ fnp-django-pagination==2.2.4 django-gravatar2==1.4.2 django-extensions==2.1.6 -raven +sentry-sdk==0.12.2 diff --git a/src/apiclient/migrations/0001_initial.py b/src/apiclient/migrations/0001_initial.py index 43f2d78f..88f51b7c 100644 --- a/src/apiclient/migrations/0001_initial.py +++ b/src/apiclient/migrations/0001_initial.py @@ -20,7 +20,7 @@ class Migration(migrations.Migration): ('token', models.CharField(max_length=64, null=True, blank=True)), ('token_secret', models.CharField(max_length=64, null=True, blank=True)), ('beta', models.BooleanField(default=False)), - ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)), ], options={ }, diff --git a/src/apiclient/models.py b/src/apiclient/models.py index 64130bc1..c750e6a6 100644 --- a/src/apiclient/models.py +++ b/src/apiclient/models.py @@ -3,7 +3,7 @@ from django.contrib.auth.models import User class OAuthConnection(models.Model): - user = models.ForeignKey(User) + user = models.ForeignKey(User, models.CASCADE) access = models.BooleanField(default=False) token = models.CharField(max_length=64, null=True, blank=True) token_secret = models.CharField(max_length=64, null=True, blank=True) diff --git a/src/apiclient/views.py b/src/apiclient/views.py index 239682a5..8d0a7983 100644 --- a/src/apiclient/views.py +++ b/src/apiclient/views.py @@ -1,7 +1,7 @@ import cgi from django.contrib.auth.decorators import login_required -from django.core.urlresolvers import reverse +from django.urls import reverse from django.http import HttpResponseRedirect, HttpResponse import oauth2 diff --git a/src/catalogue/migrations/0001_initial.py b/src/catalogue/migrations/0001_initial.py index 2dd2336d..794db482 100644 --- a/src/catalogue/migrations/0001_initial.py +++ b/src/catalogue/migrations/0001_initial.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from django.db import models, migrations import datetime import django.db.models.deletion @@ -46,8 +43,8 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('timestamp', models.DateTimeField(auto_now_add=True, verbose_name='time')), - ('book', models.ForeignKey(related_name='publish_log', verbose_name='book', to='catalogue.Book')), - ('user', models.ForeignKey(verbose_name='user', to=settings.AUTH_USER_MODEL)), + ('book', models.ForeignKey(related_name='publish_log', verbose_name='book', to='catalogue.Book', on_delete=models.CASCADE)), + ('user', models.ForeignKey(verbose_name='user', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)), ], options={ 'ordering': ['-timestamp'], @@ -67,8 +64,8 @@ class Migration(migrations.Migration): ('_short_html', models.TextField(null=True, editable=False, blank=True)), ('_hidden', models.NullBooleanField(editable=False)), ('_changed', models.NullBooleanField(editable=False)), - ('book', models.ForeignKey(editable=False, to='catalogue.Book', verbose_name='book')), - ('creator', models.ForeignKey(related_name='created_chunk', blank=True, editable=False, to=settings.AUTH_USER_MODEL, null=True, verbose_name='creator')), + ('book', models.ForeignKey(editable=False, to='catalogue.Book', verbose_name='book', on_delete=models.CASCADE)), + ('creator', models.ForeignKey(related_name='created_chunk', blank=True, editable=False, to=settings.AUTH_USER_MODEL, null=True, verbose_name='creator', on_delete=models.CASCADE)), ], options={ 'ordering': ['number'], @@ -89,9 +86,9 @@ class Migration(migrations.Migration): ('created_at', models.DateTimeField(default=datetime.datetime.now, editable=False, db_index=True)), ('publishable', models.BooleanField(default=False, verbose_name='publishable')), ('data', models.FileField(upload_to=dvcs.models.data_upload_to, storage=dvcs.storage.GzipFileSystemStorage(location=settings.CATALOGUE_REPO_PATH), verbose_name='data')), - ('author', models.ForeignKey(verbose_name='author', blank=True, to=settings.AUTH_USER_MODEL, null=True)), - ('merge_parent', models.ForeignKey(related_name='merge_children', default=None, blank=True, to='catalogue.ChunkChange', null=True, verbose_name='merge parent')), - ('parent', models.ForeignKey(related_name='children', default=None, blank=True, to='catalogue.ChunkChange', null=True, verbose_name='parent')), + ('author', models.ForeignKey(verbose_name='author', blank=True, to=settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE)), + ('merge_parent', models.ForeignKey(related_name='merge_children', default=None, blank=True, to='catalogue.ChunkChange', null=True, verbose_name='merge parent', on_delete=models.CASCADE)), + ('parent', models.ForeignKey(related_name='children', default=None, blank=True, to='catalogue.ChunkChange', null=True, verbose_name='parent', on_delete=models.CASCADE)), ], options={ 'ordering': ('created_at',), @@ -105,8 +102,8 @@ class Migration(migrations.Migration): name='ChunkPublishRecord', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('book_record', models.ForeignKey(verbose_name='book publish record', to='catalogue.BookPublishRecord')), - ('change', models.ForeignKey(related_name='publish_log', verbose_name='change', to='catalogue.ChunkChange')), + ('book_record', models.ForeignKey(verbose_name='book publish record', to='catalogue.BookPublishRecord', on_delete=models.CASCADE)), + ('change', models.ForeignKey(related_name='publish_log', verbose_name='change', to='catalogue.ChunkChange', on_delete=models.CASCADE)), ], options={ 'verbose_name': 'chunk publish record', @@ -142,7 +139,7 @@ class Migration(migrations.Migration): ('_new_publishable', models.NullBooleanField(editable=False)), ('_published', models.NullBooleanField(editable=False)), ('_changed', models.NullBooleanField(editable=False)), - ('creator', models.ForeignKey(related_name='created_image', blank=True, editable=False, to=settings.AUTH_USER_MODEL, null=True, verbose_name='creator')), + ('creator', models.ForeignKey(related_name='created_image', blank=True, editable=False, to=settings.AUTH_USER_MODEL, null=True, verbose_name='creator', on_delete=models.CASCADE)), ], options={ 'ordering': ['title'], @@ -163,9 +160,9 @@ class Migration(migrations.Migration): ('created_at', models.DateTimeField(default=datetime.datetime.now, editable=False, db_index=True)), ('publishable', models.BooleanField(default=False, verbose_name='publishable')), ('data', models.FileField(upload_to=dvcs.models.data_upload_to, storage=dvcs.storage.GzipFileSystemStorage(location=settings.CATALOGUE_IMAGE_REPO_PATH), verbose_name='data')), - ('author', models.ForeignKey(verbose_name='author', blank=True, to=settings.AUTH_USER_MODEL, null=True)), - ('merge_parent', models.ForeignKey(related_name='merge_children', default=None, blank=True, to='catalogue.ImageChange', null=True, verbose_name='merge parent')), - ('parent', models.ForeignKey(related_name='children', default=None, blank=True, to='catalogue.ImageChange', null=True, verbose_name='parent')), + ('author', models.ForeignKey(verbose_name='author', blank=True, to=settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE)), + ('merge_parent', models.ForeignKey(related_name='merge_children', default=None, blank=True, to='catalogue.ImageChange', null=True, verbose_name='merge parent', on_delete=models.CASCADE)), + ('parent', models.ForeignKey(related_name='children', default=None, blank=True, to='catalogue.ImageChange', null=True, verbose_name='parent', on_delete=models.CASCADE)), ], options={ 'ordering': ('created_at',), @@ -180,9 +177,9 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('timestamp', models.DateTimeField(auto_now_add=True, verbose_name='time')), - ('change', models.ForeignKey(related_name='publish_log', verbose_name='change', to='catalogue.ImageChange')), - ('image', models.ForeignKey(related_name='publish_log', verbose_name='image', to='catalogue.Image')), - ('user', models.ForeignKey(verbose_name='user', to=settings.AUTH_USER_MODEL)), + ('change', models.ForeignKey(related_name='publish_log', verbose_name='change', to='catalogue.ImageChange', on_delete=models.CASCADE)), + ('image', models.ForeignKey(related_name='publish_log', verbose_name='image', to='catalogue.Image', on_delete=models.CASCADE)), + ('user', models.ForeignKey(verbose_name='user', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)), ], options={ 'ordering': ['-timestamp'], @@ -230,7 +227,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='imagechange', name='tree', - field=models.ForeignKey(related_name='change_set', verbose_name='document', to='catalogue.Image'), + field=models.ForeignKey(related_name='change_set', verbose_name='document', to='catalogue.Image', on_delete=models.CASCADE), preserve_default=True, ), migrations.AlterUniqueTogether( @@ -240,25 +237,25 @@ class Migration(migrations.Migration): migrations.AddField( model_name='image', name='head', - field=models.ForeignKey(default=None, editable=False, to='catalogue.ImageChange', blank=True, help_text="This document's current head.", null=True, verbose_name='head'), + field=models.ForeignKey(default=None, editable=False, to='catalogue.ImageChange', blank=True, help_text="This document's current head.", null=True, verbose_name='head', on_delete=models.CASCADE), preserve_default=True, ), migrations.AddField( model_name='image', name='project', - field=models.ForeignKey(blank=True, to='catalogue.Project', null=True), + field=models.ForeignKey(blank=True, to='catalogue.Project', null=True, on_delete=models.CASCADE), preserve_default=True, ), migrations.AddField( model_name='image', name='stage', - field=models.ForeignKey(verbose_name='stage', blank=True, to='catalogue.ImageTag', null=True), + field=models.ForeignKey(verbose_name='stage', blank=True, to='catalogue.ImageTag', null=True, on_delete=models.CASCADE), preserve_default=True, ), migrations.AddField( model_name='image', name='user', - field=models.ForeignKey(blank=True, to=settings.AUTH_USER_MODEL, help_text='Work assignment.', null=True, verbose_name='user'), + field=models.ForeignKey(blank=True, to=settings.AUTH_USER_MODEL, help_text='Work assignment.', null=True, verbose_name='user', on_delete=models.CASCADE), preserve_default=True, ), migrations.AddField( @@ -270,7 +267,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='chunkchange', name='tree', - field=models.ForeignKey(related_name='change_set', verbose_name='document', to='catalogue.Chunk'), + field=models.ForeignKey(related_name='change_set', verbose_name='document', to='catalogue.Chunk', on_delete=models.CASCADE), preserve_default=True, ), migrations.AlterUniqueTogether( @@ -280,19 +277,19 @@ class Migration(migrations.Migration): migrations.AddField( model_name='chunk', name='head', - field=models.ForeignKey(default=None, editable=False, to='catalogue.ChunkChange', blank=True, help_text="This document's current head.", null=True, verbose_name='head'), + field=models.ForeignKey(default=None, editable=False, to='catalogue.ChunkChange', blank=True, help_text="This document's current head.", null=True, verbose_name='head', on_delete=models.CASCADE), preserve_default=True, ), migrations.AddField( model_name='chunk', name='stage', - field=models.ForeignKey(verbose_name='stage', blank=True, to='catalogue.ChunkTag', null=True), + field=models.ForeignKey(verbose_name='stage', blank=True, to='catalogue.ChunkTag', null=True, on_delete=models.CASCADE), preserve_default=True, ), migrations.AddField( model_name='chunk', name='user', - field=models.ForeignKey(blank=True, to=settings.AUTH_USER_MODEL, help_text='Work assignment.', null=True, verbose_name='user'), + field=models.ForeignKey(blank=True, to=settings.AUTH_USER_MODEL, help_text='Work assignment.', null=True, verbose_name='user', on_delete=models.CASCADE), preserve_default=True, ), migrations.AlterUniqueTogether( @@ -308,13 +305,13 @@ class Migration(migrations.Migration): migrations.AddField( model_name='book', name='parent', - field=models.ForeignKey(related_name='children', blank=True, editable=False, to='catalogue.Book', null=True, verbose_name='parent'), + field=models.ForeignKey(related_name='children', blank=True, editable=False, to='catalogue.Book', null=True, verbose_name='parent', on_delete=models.CASCADE), preserve_default=True, ), migrations.AddField( model_name='book', name='project', - field=models.ForeignKey(blank=True, to='catalogue.Project', null=True), + field=models.ForeignKey(blank=True, to='catalogue.Project', null=True, on_delete=models.CASCADE), preserve_default=True, ), migrations.CreateModel( diff --git a/src/catalogue/migrations/0004_auto_20191002_1224.py b/src/catalogue/migrations/0004_auto_20191002_1224.py new file mode 100644 index 00000000..443e7771 --- /dev/null +++ b/src/catalogue/migrations/0004_auto_20191002_1224.py @@ -0,0 +1,105 @@ +# Generated by Django 2.0.13 on 2019-10-02 12:24 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('catalogue', '0003_chunk__new_publishable'), + ] + + operations = [ + migrations.AlterField( + model_name='book', + name='parent', + field=models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='children', to='catalogue.Book', verbose_name='parent'), + ), + migrations.AlterField( + model_name='book', + name='project', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='catalogue.Project'), + ), + migrations.AlterField( + model_name='chunk', + name='creator', + field=models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_chunk', to=settings.AUTH_USER_MODEL, verbose_name='creator'), + ), + migrations.AlterField( + model_name='chunk', + name='head', + field=models.ForeignKey(blank=True, default=None, editable=False, help_text="This document's current head.", null=True, on_delete=django.db.models.deletion.SET_NULL, to='catalogue.ChunkChange', verbose_name='head'), + ), + migrations.AlterField( + model_name='chunk', + name='user', + field=models.ForeignKey(blank=True, help_text='Work assignment.', null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='user'), + ), + migrations.AlterField( + model_name='chunkchange', + name='author', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='author'), + ), + migrations.AlterField( + model_name='chunkchange', + name='description', + field=models.TextField(blank=True, default='', verbose_name='description'), + ), + migrations.AlterField( + model_name='chunkchange', + name='merge_parent', + field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='merge_children', to='catalogue.ChunkChange', verbose_name='merge parent'), + ), + migrations.AlterField( + model_name='chunkchange', + name='parent', + field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='children', to='catalogue.ChunkChange', verbose_name='parent'), + ), + migrations.AlterField( + model_name='image', + name='creator', + field=models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_image', to=settings.AUTH_USER_MODEL, verbose_name='creator'), + ), + migrations.AlterField( + model_name='image', + name='head', + field=models.ForeignKey(blank=True, default=None, editable=False, help_text="This document's current head.", null=True, on_delete=django.db.models.deletion.SET_NULL, to='catalogue.ImageChange', verbose_name='head'), + ), + migrations.AlterField( + model_name='image', + name='image', + field=models.FileField(upload_to='catalogue/images', verbose_name='image'), + ), + migrations.AlterField( + model_name='image', + name='project', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='catalogue.Project'), + ), + migrations.AlterField( + model_name='image', + name='user', + field=models.ForeignKey(blank=True, help_text='Work assignment.', null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='user'), + ), + migrations.AlterField( + model_name='imagechange', + name='author', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='author'), + ), + migrations.AlterField( + model_name='imagechange', + name='description', + field=models.TextField(blank=True, default='', verbose_name='description'), + ), + migrations.AlterField( + model_name='imagechange', + name='merge_parent', + field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='merge_children', to='catalogue.ImageChange', verbose_name='merge parent'), + ), + migrations.AlterField( + model_name='imagechange', + name='parent', + field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='children', to='catalogue.ImageChange', verbose_name='parent'), + ), + ] diff --git a/src/catalogue/models/book.py b/src/catalogue/models/book.py index a846f6e9..fc0e18f6 100755 --- a/src/catalogue/models/book.py +++ b/src/catalogue/models/book.py @@ -4,6 +4,7 @@ from django.contrib.sites.models import Site from django.db import models, transaction from django.template.loader import render_to_string +from django.urls import reverse from django.utils.translation import ugettext_lazy as _ from django.conf import settings from slugify import slugify @@ -26,10 +27,10 @@ class Book(models.Model): slug = models.SlugField(_('slug'), max_length=128, unique=True, db_index=True) public = models.BooleanField(_('public'), default=True, db_index=True) gallery = models.CharField(_('scan gallery name'), max_length=255, blank=True) - project = models.ForeignKey(Project, null=True, blank=True) + project = models.ForeignKey(Project, models.SET_NULL, null=True, blank=True) #wl_slug = models.CharField(_('title'), max_length=255, null=True, db_index=True, editable=False) - parent = models.ForeignKey('self', null=True, blank=True, verbose_name=_('parent'), related_name="children", editable=False) + parent = models.ForeignKey('self', models.SET_NULL, null=True, blank=True, verbose_name=_('parent'), related_name="children", editable=False) parent_number = models.IntegerField(_('parent number'), null=True, blank=True, db_index=True, editable=False) # Cache @@ -73,9 +74,8 @@ class Book(models.Model): def __str__(self): return self.title - @models.permalink def get_absolute_url(self): - return ("catalogue_book", [self.slug]) + return reverse("catalogue_book", args=[self.slug]) def correct_about(self): return "http://%s%s" % ( diff --git a/src/catalogue/models/chunk.py b/src/catalogue/models/chunk.py index 4182d08f..b3e6acaa 100755 --- a/src/catalogue/models/chunk.py +++ b/src/catalogue/models/chunk.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# # This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later. # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # @@ -7,6 +5,7 @@ from django.conf import settings from django.db import models from django.db.utils import IntegrityError from django.template.loader import render_to_string +from django.urls import reverse from django.utils.translation import ugettext_lazy as _ from catalogue.helpers import cached_in_field from catalogue.managers import VisibleManager @@ -17,7 +16,7 @@ class Chunk(dvcs_models.Document): """ An editable chunk of text. Every Book text is divided into chunks. """ REPO_PATH = settings.CATALOGUE_REPO_PATH - book = models.ForeignKey('Book', editable=False, verbose_name=_('book')) + book = models.ForeignKey('Book', models.CASCADE, editable=False, verbose_name=_('book')) number = models.IntegerField(_('number')) title = models.CharField(_('title'), max_length=255, blank=True) slug = models.SlugField(_('slug')) @@ -46,9 +45,8 @@ class Chunk(dvcs_models.Document): def __str__(self): return "%d:%d: %s" % (self.book_id, self.number, self.title) - @models.permalink def get_absolute_url(self): - return "wiki_editor", [self.book.slug, self.slug] + return reverse("wiki_editor", args=[self.book.slug, self.slug]) def pretty_name(self, book_length=None): title = self.book.title diff --git a/src/catalogue/models/image.py b/src/catalogue/models/image.py index dbe1c047..becc308b 100755 --- a/src/catalogue/models/image.py +++ b/src/catalogue/models/image.py @@ -5,6 +5,7 @@ from django.conf import settings from django.contrib.sites.models import Site from django.db import models from django.template.loader import render_to_string +from django.urls import reverse from django.utils.translation import ugettext_lazy as _ from catalogue.helpers import cached_in_field from catalogue.models import Project @@ -19,7 +20,7 @@ class Image(dvcs_models.Document): title = models.CharField(_('title'), max_length=255, blank=True) slug = models.SlugField(_('slug'), unique=True) public = models.BooleanField(_('public'), default=True, db_index=True) - project = models.ForeignKey(Project, null=True, blank=True) + project = models.ForeignKey(Project, models.SET_NULL, null=True, blank=True) # cache _new_publishable = models.NullBooleanField(editable=False) @@ -39,9 +40,8 @@ class Image(dvcs_models.Document): def __str__(self): return self.title - @models.permalink def get_absolute_url(self): - return ("catalogue_image", [self.slug]) + return reverse("catalogue_image", args=[self.slug]) def correct_about(self): return ["http://%s%s" % ( diff --git a/src/catalogue/models/publish_log.py b/src/catalogue/models/publish_log.py index 7a8e2f9e..eeec055e 100755 --- a/src/catalogue/models/publish_log.py +++ b/src/catalogue/models/publish_log.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# # This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later. # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # @@ -14,9 +12,9 @@ class BookPublishRecord(models.Model): A record left after publishing a Book. """ - book = models.ForeignKey('Book', verbose_name=_('book'), related_name='publish_log') + book = models.ForeignKey('Book', models.CASCADE, verbose_name=_('book'), related_name='publish_log') timestamp = models.DateTimeField(_('time'), auto_now_add=True) - user = models.ForeignKey(User, verbose_name=_('user')) + user = models.ForeignKey(User, models.CASCADE, verbose_name=_('user')) class Meta: app_label = 'catalogue' @@ -30,8 +28,8 @@ class ChunkPublishRecord(models.Model): BookPublishRecord details for each Chunk. """ - book_record = models.ForeignKey(BookPublishRecord, verbose_name=_('book publish record')) - change = models.ForeignKey(Chunk.change_model, related_name='publish_log', verbose_name=_('change')) + book_record = models.ForeignKey(BookPublishRecord, models.CASCADE, verbose_name=_('book publish record')) + change = models.ForeignKey(Chunk.change_model, models.CASCADE, related_name='publish_log', verbose_name=_('change')) class Meta: app_label = 'catalogue' @@ -42,10 +40,10 @@ class ChunkPublishRecord(models.Model): class ImagePublishRecord(models.Model): """A record left after publishing an Image.""" - image = models.ForeignKey(Image, verbose_name=_('image'), related_name='publish_log') + image = models.ForeignKey(Image, models.CASCADE, verbose_name=_('image'), related_name='publish_log') timestamp = models.DateTimeField(_('time'), auto_now_add=True) - user = models.ForeignKey(User, verbose_name=_('user')) - change = models.ForeignKey(Image.change_model, related_name='publish_log', verbose_name=_('change')) + user = models.ForeignKey(User, models.CASCADE, verbose_name=_('user')) + change = models.ForeignKey(Image.change_model, models.CASCADE, related_name='publish_log', verbose_name=_('change')) class Meta: app_label = 'catalogue' diff --git a/src/catalogue/templatetags/catalogue.py b/src/catalogue/templatetags/catalogue.py index 07c5cf9d..9c876ded 100644 --- a/src/catalogue/templatetags/catalogue.py +++ b/src/catalogue/templatetags/catalogue.py @@ -1,6 +1,4 @@ -from __future__ import absolute_import - -from django.core.urlresolvers import reverse +from django.urls import reverse from django import template from django.utils.translation import ugettext as _ diff --git a/src/catalogue/templatetags/wall.py b/src/catalogue/templatetags/wall.py index 0c1628ce..2dcf2ba5 100755 --- a/src/catalogue/templatetags/wall.py +++ b/src/catalogue/templatetags/wall.py @@ -1,8 +1,6 @@ -from __future__ import absolute_import - from datetime import timedelta from django.db.models import Q -from django.core.urlresolvers import reverse +from django.urls import reverse from django import template from django.utils.translation import ugettext as _ diff --git a/src/catalogue/views.py b/src/catalogue/views.py index ab1f8214..377bdbbd 100644 --- a/src/catalogue/views.py +++ b/src/catalogue/views.py @@ -8,7 +8,7 @@ from django.conf import settings from django.contrib import auth from django.contrib.auth.models import User from django.contrib.auth.decorators import login_required, permission_required -from django.core.urlresolvers import reverse +from django.urls import reverse from django.db.models import Count, Q from django.db import transaction from django import http diff --git a/src/cover/migrations/0002_auto_20191002_1224.py b/src/cover/migrations/0002_auto_20191002_1224.py new file mode 100644 index 00000000..3f5864e6 --- /dev/null +++ b/src/cover/migrations/0002_auto_20191002_1224.py @@ -0,0 +1,19 @@ +# Generated by Django 2.0.13 on 2019-10-02 12:24 + +import cover.models +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('cover', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='image', + name='file', + field=models.ImageField(storage=cover.models.OverwriteStorage(), upload_to='cover/image', verbose_name='file'), + ), + ] diff --git a/src/cover/models.py b/src/cover/models.py index ea69f654..c60efe18 100644 --- a/src/cover/models.py +++ b/src/cover/models.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# # This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later. # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # @@ -8,6 +6,7 @@ from django.core.files.storage import FileSystemStorage from django.db import models from django.db.models.signals import post_save from django.dispatch import receiver +from django.urls import reverse from django.utils.translation import ugettext_lazy as _ from django.contrib.sites.models import Site from cover.utils import URLOpener @@ -37,9 +36,8 @@ class Image(models.Model): def __str__(self): return u"%s - %s" % (self.author, self.title) - @models.permalink def get_absolute_url(self): - return 'cover_image', [self.id] + return reverse('cover_image', args=[self.id]) def get_full_url(self): return "http://%s%s" % (Site.objects.get_current().domain, self.get_absolute_url()) diff --git a/src/dvcs/models.py b/src/dvcs/models.py index d6b0cc68..adaf7955 100644 --- a/src/dvcs/models.py +++ b/src/dvcs/models.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# # This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later. # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # @@ -10,7 +8,8 @@ from django.contrib.auth.models import User from django.core.files.base import ContentFile from django.db import models, transaction from django.db.models.base import ModelBase -from django.utils.translation import string_concat, ugettext_lazy as _ +from django.utils.text import format_lazy +from django.utils.translation import ugettext_lazy as _ import merge3 from django.conf import settings @@ -71,7 +70,7 @@ class Change(models.Model): Data file contains a gzipped text of the document. """ - author = models.ForeignKey(User, null=True, blank=True, verbose_name=_('author')) + author = models.ForeignKey(User, models.SET_NULL, null=True, blank=True, verbose_name=_('author')) author_name = models.CharField( _('author name'), max_length=128, null=True, blank=True, help_text=_("Used if author is not set.")) author_email = models.CharField( @@ -79,10 +78,10 @@ class Change(models.Model): revision = models.IntegerField(_('revision'), db_index=True) parent = models.ForeignKey( - 'self', null=True, blank=True, default=None, verbose_name=_('parent'), related_name="children") + 'self', models.SET_NULL, null=True, blank=True, default=None, verbose_name=_('parent'), related_name="children") merge_parent = models.ForeignKey( - 'self', null=True, blank=True, default=None, verbose_name=_('merge parent'), related_name="merge_children") + 'self', models.SET_NULL, null=True, blank=True, default=None, verbose_name=_('merge parent'), related_name="merge_children") description = models.TextField(_('description'), blank=True, default='') created_at = models.DateTimeField(editable=False, db_index=True, default=datetime.now) @@ -165,10 +164,10 @@ def create_tag_model(model): class Meta(Tag.Meta): app_label = model._meta.app_label - verbose_name = string_concat( - _("tag"), " ", _("for:"), " ", model._meta.verbose_name) - verbose_name_plural = string_concat( - _("tags"), " ", _("for:"), " ", model._meta.verbose_name) + verbose_name = format_lazy( + '{} {} {}', _('tag'), _('for:'), model._meta.verbose_name) + verbose_name_plural = format_lazy( + '{} {} {}', _("tags"), _("for:"), model._meta.verbose_name) attrs = { '__module__': model.__module__, @@ -183,14 +182,14 @@ def create_change_model(model): class Meta(Change.Meta): app_label = model._meta.app_label - verbose_name = string_concat( - _("change"), " ", _("for:"), " ", model._meta.verbose_name) - verbose_name_plural = string_concat( - _("changes"), " ", _("for:"), " ", model._meta.verbose_name) + verbose_name = format_lazy( + '{} {} {}', _("change"), _("for:"), model._meta.verbose_name) + verbose_name_plural = format_lazy( + '{} {} {}', _("changes"), _("for:"), model._meta.verbose_name) attrs = { '__module__': model.__module__, - 'tree': models.ForeignKey(model, related_name='change_set', verbose_name=_('document')), + 'tree': models.ForeignKey(model, models.CASCADE, related_name='change_set', verbose_name=_('document')), 'tags': models.ManyToManyField(model.tag_model, verbose_name=_('tags'), related_name='change_set'), 'data': models.FileField(_('data'), upload_to=data_upload_to, storage=repo), 'Meta': Meta, @@ -206,19 +205,19 @@ class DocumentMeta(ModelBase): if not model._meta.abstract: # create a real Tag object and `stage' fk model.tag_model = create_tag_model(model) - models.ForeignKey(model.tag_model, verbose_name=_('stage'), + models.ForeignKey(model.tag_model, models.CASCADE, verbose_name=_('stage'), null=True, blank=True).contribute_to_class(model, 'stage') # create real Change model and `head' fk model.change_model = create_change_model(model) models.ForeignKey( - model.change_model, null=True, blank=True, default=None, + model.change_model, models.SET_NULL, null=True, blank=True, default=None, verbose_name=_('head'), help_text=_("This document's current head."), editable=False).contribute_to_class(model, 'head') models.ForeignKey( - User, null=True, blank=True, editable=False, + User, models.SET_NULL, null=True, blank=True, editable=False, verbose_name=_('creator'), related_name="created_%s" % name.lower() ).contribute_to_class(model, 'creator') @@ -231,7 +230,7 @@ class Document(models.Model, metaclass=DocumentMeta): # default repository path REPO_PATH = os.path.join(settings.MEDIA_ROOT, 'dvcs') - user = models.ForeignKey(User, null=True, blank=True, verbose_name=_('user'), help_text=_('Work assignment.')) + user = models.ForeignKey(User, models.SET_NULL, null=True, blank=True, verbose_name=_('user'), help_text=_('Work assignment.')) class Meta: abstract = True @@ -280,7 +279,7 @@ class Document(models.Model, metaclass=DocumentMeta): author=author, author_name=author_name, author_email=author_email, description=kwargs.get('description', ''), publishable=publishable, parent=parent) - change.tags = tags + change.tags.set(tags) change.data.save('', ContentFile(text.encode('utf-8'))) change.save() diff --git a/src/redakcja/settings/__init__.py b/src/redakcja/settings/__init__.py index 571a9ed2..71bc998c 100644 --- a/src/redakcja/settings/__init__.py +++ b/src/redakcja/settings/__init__.py @@ -1,9 +1,8 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import import os.path +import sentry_sdk +from sentry_sdk.integrations.django import DjangoIntegration from .defaults import * from ..localsettings import * -import os PROJECT_ROOT = os.path.realpath(os.path.dirname(os.path.dirname(__file__))) @@ -66,7 +65,6 @@ INSTALLED_APPS = ( 'django.contrib.sites', 'django.contrib.admin', 'django.contrib.admindocs', - 'raven.contrib.django.raven_compat', 'sorl.thumbnail', 'fnp_django_pagination', @@ -237,3 +235,15 @@ PIPELINE = { } } } + + +try: + SENTRY_DSN +except NameError: + pass +else: + sentry_sdk.init( + dsn=SENTRY_DSN, + integrations=[DjangoIntegration()] + ) + diff --git a/src/redakcja/urls.py b/src/redakcja/urls.py index 54ed920d..2ecb7ed4 100644 --- a/src/redakcja/urls.py +++ b/src/redakcja/urls.py @@ -9,8 +9,6 @@ from django.views.generic import RedirectView import django_cas_ng.views -admin.autodiscover() - urlpatterns = [ # Auth url(r'^accounts/login/$', django_cas_ng.views.LoginView.as_view(), name='cas_ng_login'), @@ -20,7 +18,7 @@ urlpatterns = [ # Admin panel url(r'^admin/doc/', include('django.contrib.admindocs.urls')), - url(r'^admin/', include(admin.site.urls)), + url(r'^admin/', admin.site.urls), url(r'^$', RedirectView.as_view(url= '/documents/', permanent=False)), url(r'^documents/', include('catalogue.urls')), diff --git a/src/toolbar/migrations/0001_initial.py b/src/toolbar/migrations/0001_initial.py index e3a24044..e396fac1 100644 --- a/src/toolbar/migrations/0001_initial.py +++ b/src/toolbar/migrations/0001_initial.py @@ -62,7 +62,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='button', name='scriptlet', - field=models.ForeignKey(blank=True, to='toolbar.Scriptlet', null=True), + field=models.ForeignKey(blank=True, to='toolbar.Scriptlet', null=True, on_delete=models.CASCADE), preserve_default=True, ), ] diff --git a/src/toolbar/migrations/0002_auto_20191002_1224.py b/src/toolbar/migrations/0002_auto_20191002_1224.py new file mode 100644 index 00000000..b2f134b6 --- /dev/null +++ b/src/toolbar/migrations/0002_auto_20191002_1224.py @@ -0,0 +1,29 @@ +# Generated by Django 2.0.13 on 2019-10-02 12:24 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('toolbar', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='button', + name='link', + field=models.CharField(blank=True, default='', max_length=256), + ), + migrations.AlterField( + model_name='button', + name='params', + field=models.TextField(default='[]'), + ), + migrations.AlterField( + model_name='button', + name='scriptlet', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='toolbar.Scriptlet'), + ), + ] diff --git a/src/toolbar/models.py b/src/toolbar/models.py index fbaa396e..02567fab 100644 --- a/src/toolbar/models.py +++ b/src/toolbar/models.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# # This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later. # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # @@ -34,7 +32,7 @@ class Button(models.Model): # behaviour params = models.TextField(default='[]') # TODO: should be a JSON field - scriptlet = models.ForeignKey('Scriptlet', null=True, blank=True) + scriptlet = models.ForeignKey('Scriptlet', models.SET_NULL, null=True, blank=True) link = models.CharField(max_length=256, blank=True, default='') # ui related stuff diff --git a/src/wiki/forms.py b/src/wiki/forms.py index 3ef3ed14..6f6defc6 100644 --- a/src/wiki/forms.py +++ b/src/wiki/forms.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# # This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later. # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # @@ -67,7 +65,7 @@ class DocumentTextSaveForm(forms.Form): def __init__(self, *args, **kwargs): user = kwargs.pop('user') r = super(DocumentTextSaveForm, self).__init__(*args, **kwargs) - if user and user.is_authenticated(): + if user and user.is_authenticated: self.fields['author_name'].required = False self.fields['author_email'].required = False return r diff --git a/src/wiki/helpers.py b/src/wiki/helpers.py index d62c5459..6ad6bb63 100644 --- a/src/wiki/helpers.py +++ b/src/wiki/helpers.py @@ -44,7 +44,7 @@ class JSONServerError(JSONResponse): def ajax_login_required(view): @wraps(view) def authenticated_view(request, *args, **kwargs): - if not request.user.is_authenticated(): + if not request.user.is_authenticated: return http.HttpResponse("Login required.", status=401, content_type="text/plain") return view(request, *args, **kwargs) return authenticated_view diff --git a/src/wiki/views.py b/src/wiki/views.py index 332f28fb..6b3586c1 100644 --- a/src/wiki/views.py +++ b/src/wiki/views.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from datetime import datetime import os import logging @@ -6,7 +5,7 @@ from time import mktime from urllib.parse import quote from django.conf import settings -from django.core.urlresolvers import reverse +from django.urls import reverse from django import http from django.http import Http404, HttpResponseForbidden from django.middleware.gzip import GZipMiddleware @@ -115,7 +114,7 @@ def text(request, chunk_id): if request.method == 'POST': form = forms.DocumentTextSaveForm(request.POST, user=request.user, prefix="textsave") if form.is_valid(): - if request.user.is_authenticated(): + if request.user.is_authenticated: author = request.user else: author = None @@ -180,7 +179,7 @@ def revert(request, chunk_id): comment = form.cleaned_data['comment'] comment += "\n#revert to %s" % revision - if request.user.is_authenticated(): + if request.user.is_authenticated: author = request.user else: author = None @@ -222,7 +221,7 @@ def gallery(request, directory): books = Book.objects.filter(gallery=directory) - if not all(book.public for book in books) and not request.user.is_authenticated(): + if not all(book.public for book in books) and not request.user.is_authenticated: return HttpResponseForbidden("Not authorized.") return JSONResponse(images) diff --git a/src/wiki_img/views.py b/src/wiki_img/views.py index e5bbf410..adbad5ca 100644 --- a/src/wiki_img/views.py +++ b/src/wiki_img/views.py @@ -3,7 +3,7 @@ import functools import logging logger = logging.getLogger("fnp.wiki_img") -from django.core.urlresolvers import reverse +from django.urls import reverse from wiki.helpers import (JSONResponse, JSONFormInvalid, JSONServerError, ajax_require_permission) @@ -63,7 +63,7 @@ def text(request, image_id): if request.method == 'POST': form = ImageSaveForm(request.POST, user=request.user, prefix="textsave") if form.is_valid(): - if request.user.is_authenticated(): + if request.user.is_authenticated: author = request.user else: author = None @@ -148,7 +148,7 @@ def revert(request, object_id): comment = form.cleaned_data['comment'] comment += "\n#revert to %s" % revision - if request.user.is_authenticated(): + if request.user.is_authenticated: author = request.user else: author = None