--- a/.hgignore Thu Oct 12 17:33:22 2017 +0200
+++ b/.hgignore Mon May 14 14:45:22 2018 +0200
@@ -34,5 +34,7 @@
^src/.vscode
^src/requirements/custom.txt$
^src/iconolab/db.sqlite3
+^src/.direnv
+^src/.envrc$
^data/
--- a/src/iconolab/auth/urls.py Thu Oct 12 17:33:22 2017 +0200
+++ b/src/iconolab/auth/urls.py Mon May 14 14:45:22 2018 +0200
@@ -4,6 +4,7 @@
from django.contrib.auth.views import login, logout, password_change
from . import views
+app_name="iconolab-auth"
urlpatterns = [
url(r'^register/$', views.RegisterView.as_view(), name='register'),
url(r'^register/created/$', views.UserCreatedView.as_view(), name='user_created'),
--- a/src/iconolab/auth/views.py Thu Oct 12 17:33:22 2017 +0200
+++ b/src/iconolab/auth/views.py Mon May 14 14:45:22 2018 +0200
@@ -2,7 +2,7 @@
from django.contrib.auth import authenticate, login, logout, get_user_model
from iconolab.auth.forms import UserCreationForm
from django.shortcuts import redirect, render, HttpResponseRedirect
-from django.core.urlresolvers import reverse_lazy
+from django.urls import reverse_lazy
from django.contrib.auth.forms import AuthenticationForm
from django.views.generic import FormView
from django.views.generic.base import RedirectView, TemplateView
@@ -32,7 +32,7 @@
return context
def get(self, request, *args, **kwargs):
- if request.user.is_authenticated():
+ if request.user.is_authenticated:
return HttpResponseRedirect(self.get_success_url())
return super(LoginView, self).get(request, *args, **kwargs)
--- a/src/iconolab/forms/bookmarks.py Thu Oct 12 17:33:22 2017 +0200
+++ b/src/iconolab/forms/bookmarks.py Mon May 14 14:45:22 2018 +0200
@@ -18,7 +18,7 @@
user = kwargs.pop('user', None)
super(BookmarkForm, self).__init__(*args, **kwargs)
- if user.is_authenticated():
+ if user.is_authenticated:
self.user = user
--- a/src/iconolab/mails.py Thu Oct 12 17:33:22 2017 +0200
+++ b/src/iconolab/mails.py Mon May 14 14:45:22 2018 +0200
@@ -1,9 +1,7 @@
from django.conf import settings
from django.contrib.sites.models import Site
from django.core.mail import send_mail
-from django.core.urlresolvers import reverse
-
-current_site = Site.objects.get_current()
+from django.urls import reverse
class EmailManager():
@@ -15,6 +13,7 @@
VERB_REQUEST_FOR_EXPERTISE = 'a fait un appel à expertise'
def __message_content(self, verb):
+ current_site = Site.objects.get_current()
notifications_url = 'http://' + current_site.domain + reverse('user_notifications')
message = 'Un utilisateur ' + verb + '\n'
--- a/src/iconolab/models.py Thu Oct 12 17:33:22 2017 +0200
+++ b/src/iconolab/models.py Mon May 14 14:45:22 2018 +0200
@@ -75,7 +75,7 @@
Some items may belong to a "folder". This is actually a physical folder
"""
folder_guid = models.UUIDField(default=uuid.uuid4, editable=False)
- collection = models.ForeignKey(Collection, related_name="folders")
+ collection = models.ForeignKey(Collection, related_name="folders", on_delete=models.PROTECT)
name = models.TextField(null=False, blank=False)
description = models.TextField(null=True, blank=True)
original_id = models.CharField(max_length=256, null=True, blank=True)
@@ -109,7 +109,7 @@
Item objects belong to a collection, are linked to a metadata item, and
to one or more images
"""
- collection = models.ForeignKey(Collection, related_name="items")
+ collection = models.ForeignKey(Collection, related_name="items", on_delete=models.PROTECT)
item_guid = models.UUIDField(default=uuid.uuid4, editable=False)
folders = models.ManyToManyField('Folder')
@@ -128,7 +128,7 @@
Metadata object for the item class. Each field represents what we can
import from the provided .csv files
"""
- item = models.OneToOneField('Item', related_name='metadatas')
+ item = models.OneToOneField('Item', related_name='metadatas', on_delete=models.PROTECT)
authors = models.CharField(max_length=255, default="")
school = models.CharField(max_length=255, default="")
field = models.CharField(max_length=255, default="")
@@ -161,7 +161,7 @@
media = models.ImageField(upload_to='uploads/',
height_field='height', width_field='width')
item = models.ForeignKey(
- 'Item', related_name='images', null=True, blank=True)
+ 'Item', related_name='images', null=True, blank=True, on_delete=models.PROTECT)
height = models.IntegerField(null=False, blank=False)
width = models.IntegerField(null=False, blank=False)
created = models.DateTimeField(auto_now_add=True, null=True)
@@ -229,7 +229,7 @@
displayed in image and item pages
"""
image = models.OneToOneField(
- 'Image', related_name='stats', blank=False, null=False)
+ 'Image', related_name='stats', blank=False, null=False, on_delete=models.PROTECT)
views_count = models.IntegerField(blank=True, null=True, default=0)
annotations_count = models.IntegerField(blank=True, null=True, default=0)
submitted_revisions_count = models.IntegerField(
@@ -430,10 +430,10 @@
image = models.ForeignKey(
'Image', related_name='annotations', on_delete=models.CASCADE)
source_revision = models.ForeignKey(
- 'AnnotationRevision', related_name='source_related_annotation', blank=True, null=True)
+ 'AnnotationRevision', related_name='source_related_annotation', blank=True, null=True, on_delete=models.PROTECT)
current_revision = models.OneToOneField(
- 'AnnotationRevision', related_name='current_for_annotation', blank=True, null=True)
- author = models.ForeignKey(User, null=True)
+ 'AnnotationRevision', related_name='current_for_annotation', blank=True, null=True, on_delete=models.PROTECT)
+ author = models.ForeignKey(User, null=True, on_delete=models.PROTECT)
created = models.DateTimeField(auto_now_add=True, null=True)
comments = GenericRelation(
'IconolabComment', content_type_field='content_type_id', object_id_field='object_pk')
@@ -561,7 +561,7 @@
displayed in annotation pages
"""
annotation = models.OneToOneField(
- 'Annotation', related_name='stats', blank=False, null=False)
+ 'Annotation', related_name='stats', blank=False, null=False, on_delete=models.PROTECT)
submitted_revisions_count = models.IntegerField(
blank=True, null=True, default=1)
awaiting_revisions_count = models.IntegerField(
@@ -705,12 +705,12 @@
revision_guid = models.UUIDField(default=uuid.uuid4)
annotation = models.ForeignKey(
- 'Annotation', related_name='revisions', null=False, blank=False)
+ 'Annotation', related_name='revisions', null=False, blank=False, on_delete=models.PROTECT)
parent_revision = models.ForeignKey(
- 'AnnotationRevision', related_name='child_revisions', blank=True, null=True)
+ 'AnnotationRevision', related_name='child_revisions', blank=True, null=True, on_delete=models.PROTECT)
merge_parent_revision = models.ForeignKey(
- 'AnnotationRevision', related_name='child_revisions_merge', blank=True, null=True)
- author = models.ForeignKey(User, null=True)
+ 'AnnotationRevision', related_name='child_revisions_merge', blank=True, null=True, on_delete=models.PROTECT)
+ author = models.ForeignKey(User, null=True, on_delete=models.PROTECT)
title = models.CharField(max_length=255)
description = models.TextField(null=True)
fragment = models.TextField()
@@ -879,7 +879,7 @@
label_slug = models.SlugField(blank=True, null=True)
link = models.URLField(unique=True)
description = models.CharField(max_length=255, blank=True, null=True)
- collection = models.ForeignKey('Collection', blank=True, null=True)
+ collection = models.ForeignKey('Collection', blank=True, null=True, on_delete=models.PROTECT)
def is_internal(self):
return self.link.startswith(settings.INTERNAL_TAGS_URL)
@@ -912,7 +912,7 @@
Each comment can have a set of metacategories
"""
revision = models.ForeignKey(
- 'AnnotationRevision', related_name='creation_comment', null=True, blank=True)
+ 'AnnotationRevision', related_name='creation_comment', null=True, blank=True, on_delete=models.PROTECT)
metacategories = models.ManyToManyField(
'MetaCategory', through='MetaCategoryInfo', through_fields=('comment', 'metacategory'))
@@ -983,7 +983,7 @@
(DISAGREEMENT, 'disagreement'),
)
- collection = models.ForeignKey(Collection, related_name="metacategories")
+ collection = models.ForeignKey(Collection, related_name="metacategories", on_delete=models.PROTECT)
label = models.CharField(max_length=255)
triggers_notifications = models.IntegerField(
choices=NOTIFIED_USERS, default=NONE)
@@ -1042,11 +1042,11 @@
class BookmarkCategory(models.Model):
- user = models.ForeignKey(User)
+ user = models.ForeignKey(User, on_delete=models.PROTECT)
name = models.CharField(max_length=255)
created = models.DateTimeField(auto_now_add=True)
class Bookmark(models.Model):
- category = models.ForeignKey(BookmarkCategory)
- image = models.ForeignKey(Image)
+ category = models.ForeignKey(BookmarkCategory, on_delete=models.PROTECT)
+ image = models.ForeignKey(Image, on_delete=models.PROTECT)
created = models.DateTimeField(auto_now_add=True)
--- a/src/iconolab/search_indexes/urls.py Thu Oct 12 17:33:22 2017 +0200
+++ b/src/iconolab/search_indexes/urls.py Mon May 14 14:45:22 2018 +0200
@@ -3,6 +3,7 @@
from django.conf.urls import url
from . import views
+app_name = "iconolab-search_indexes"
urlpatterns = [
url(r'collection/(?P<collection_name>[a-z0-9\-]+)/model/(?P<model_type>[a-z0-9\-]+)', views.IconolabSearchView.as_view(), name="collection_with_model_search"),
url(r'collection/(?P<collection_name>[a-z0-9\-]+)', views.IconolabSearchView.as_view(), name="collection_haystack_search"),
--- a/src/iconolab/search_indexes/views.py Thu Oct 12 17:33:22 2017 +0200
+++ b/src/iconolab/search_indexes/views.py Mon May 14 14:45:22 2018 +0200
@@ -2,7 +2,7 @@
from haystack.query import RelatedSearchQuerySet
from iconolab.search_indexes.forms import IconolabSearchForm
from django.shortcuts import HttpResponse, redirect
-from django.core.urlresolvers import reverse
+from django.urls import reverse
from django.views.generic import RedirectView
from iconolab.models import Collection
--- a/src/iconolab/settings/__init__.py Thu Oct 12 17:33:22 2017 +0200
+++ b/src/iconolab/settings/__init__.py Mon May 14 14:45:22 2018 +0200
@@ -67,13 +67,12 @@
SITE_ID = 1
-MIDDLEWARE_CLASSES = [
+MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
- 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
--- a/src/iconolab/templates/iconolab/detail_image.html Thu Oct 12 17:33:22 2017 +0200
+++ b/src/iconolab/templates/iconolab/detail_image.html Mon May 14 14:45:22 2018 +0200
@@ -131,7 +131,7 @@
var annotations = [];
{% if image.annotations.exists %}
{% for annotation in image.latest_annotations %}
- annotations.push({{ annotation.current_revision|json|safe }});
+ annotations.push(JSON.parse("{{ annotation.current_revision|json|addslashes|safe }}"));
{% endfor %}
{% endif %}
--- a/src/iconolab/templatetags/iconolab_tags.py Thu Oct 12 17:33:22 2017 +0200
+++ b/src/iconolab/templatetags/iconolab_tags.py Mon May 14 14:45:22 2018 +0200
@@ -11,43 +11,43 @@
# {% transform_matrix 230 200 100 100 %}
@register.simple_tag
def transform_matrix(im_width=0, im_height=0, max_x=0, max_y=0):
- try :
- x_ratio = im_width / max_x
- y_ratio = im_height / max_y
- value_list = [x_ratio, 0, 0, y_ratio, 0, 0]
- matrix = ",".join([str(v) for v in value_list])
- except:
- matrix = ""
+ try :
+ x_ratio = im_width / max_x
+ y_ratio = im_height / max_y
+ value_list = [x_ratio, 0, 0, y_ratio, 0, 0]
+ matrix = ",".join([str(v) for v in value_list])
+ except:
+ matrix = ""
- return matrix
+ return matrix
@register.filter
def clean_path(path):
- result = ""
- if not len(path):
- return result
- else:
- path_infos = path.split(";")
- if len(path_infos) > 0 :
- result = path_infos[0]
- return result
+ result = ""
+ if not len(path):
+ return result
+ else:
+ path_infos = path.split(";")
+ if len(path_infos) > 0 :
+ result = path_infos[0]
+ return result
@register.filter
def path_type(path):
- result = ""
- if not len(path):
- return result
- else:
- path_infos = path.split(";")
- if len(path_infos) > 1 :
- result = path_infos[1]
+ result = ""
+ if not len(path):
+ return result
+ else:
+ path_infos = path.split(";")
+ if len(path_infos) > 1 :
+ result = path_infos[1]
- return result
+ return result
@register.simple_tag
def version():
- return __version__
+ return __version__
@register.filter
def get_item(dictionary, key):
@@ -63,7 +63,7 @@
def json_dumps(data):
if isinstance(data, AnnotationRevision) :
serializer = AnnotationRevisionSerializer(data)
- return JSONRenderer().render(serializer.data)
+ return JSONRenderer().render(serializer.data).decode('utf-8')
return serialize('json', [data])
@register.simple_tag(takes_context=True)
@@ -74,9 +74,9 @@
return 'container-fluid'
return 'container'
-@register.assignment_tag(takes_context=True)
+@register.simple_tag(takes_context=True)
def is_bookmarked(context, image):
request = context['request']
- if not request.user.is_authenticated():
+ if not request.user.is_authenticated:
return False
return image.is_bookmarked_by(request.user)
--- a/src/iconolab/urls.py Thu Oct 12 17:33:22 2017 +0200
+++ b/src/iconolab/urls.py Mon May 14 14:45:22 2018 +0200
@@ -13,7 +13,7 @@
1. Import the include() function: from django.conf.urls import url, include
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
"""
-from django.core.urlresolvers import reverse_lazy
+from django.urls import reverse_lazy
from django.conf.urls import url, include
from django.contrib import admin
--- a/src/iconolab/views/comments.py Thu Oct 12 17:33:22 2017 +0200
+++ b/src/iconolab/views/comments.py Mon May 14 14:45:22 2018 +0200
@@ -21,7 +21,7 @@
'''
# Fill out some initial data fields from an authenticated user, if present
data = request.POST.copy()
- if request.user.is_authenticated():
+ if request.user.is_authenticated:
if not data.get('name', ''):
data['name'] = request.user.get_full_name() or request.user.get_username()
if not data.get('email', ''):
@@ -78,7 +78,7 @@
# Otherwise create the comment
comment = form.get_comment_object()
comment.ip_address = request.META.get('REMOTE_ADDR', None)
- if request.user.is_authenticated():
+ if request.user.is_authenticated:
comment.user = request.user
# Signal that the comment is about to be saved
--- a/src/iconolab/views/objects.py Thu Oct 12 17:33:22 2017 +0200
+++ b/src/iconolab/views/objects.py Mon May 14 14:45:22 2018 +0200
@@ -8,7 +8,7 @@
from django.contrib.sites.models import Site
from django.core.exceptions import ObjectDoesNotExist
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
-from django.core.urlresolvers import reverse
+from django.urls import reverse
from django.db.models import Count, Prefetch
from django.http import Http404
from django.shortcuts import HttpResponse, get_object_or_404, redirect, render
@@ -617,7 +617,7 @@
comments_list = paginator.page(paginator.num_pages)
context['comments'] = comments_list
- if request.user.is_authenticated():
+ if request.user.is_authenticated:
user_comment_notifications = Notification.objects.filter(
recipient=request.user,
action_object_content_type__app_label='iconolab',
@@ -794,7 +794,7 @@
context['revision'] = revision
context['tags_data'] = revision.get_tags_json()
context['comment'] = revision.creation_comment.first()
- if request.user.is_authenticated() and annotation.author == request.user:
+ if request.user.is_authenticated and annotation.author == request.user:
ann_author_notified = Notification.objects.filter(
recipient=request.user,
action_object_content_type__app_label='iconolab',
@@ -807,7 +807,7 @@
if ann_author_notified:
ann_author_notified.first().mark_as_read()
context['notified_revision'] = True
- if request.user.is_authenticated() and revision.author == request.user:
+ if request.user.is_authenticated and revision.author == request.user:
rev_author_notified = Notification.objects.filter(
recipient=request.user,
action_object_content_type__app_label='iconolab',
--- a/src/iconolab/views/userpages.py Thu Oct 12 17:33:22 2017 +0200
+++ b/src/iconolab/views/userpages.py Mon May 14 14:45:22 2018 +0200
@@ -1,6 +1,6 @@
from django.shortcuts import HttpResponse, get_object_or_404, render, redirect
from django.views.generic import View, DetailView
-from django.core.urlresolvers import reverse_lazy
+from django.urls import reverse_lazy
from django.core.exceptions import ObjectDoesNotExist
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.contrib.auth.models import User
@@ -63,7 +63,7 @@
context = {}
notifications = Notification.objects.filter(recipient=request.user)
- if request.user.is_authenticated() and 'clear_notifications' in request.GET:
+ if request.user.is_authenticated and 'clear_notifications' in request.GET:
Notification.objects.filter(recipient=request.user).mark_all_as_read()
context['notifications_unread_ids'] = notifications.unread().values_list('id', flat=True)
@@ -149,7 +149,7 @@
def post(self, request, *args, **kwargs):
- if request.user.is_authenticated():
+ if request.user.is_authenticated:
bookmark_id = kwargs.get('bookmark')
bookmark = Bookmark.objects.get(id=bookmark_id)
if bookmark.category.user == request.user:
@@ -165,7 +165,7 @@
def post(self, request, *args, **kwargs):
- if request.user.is_authenticated():
+ if request.user.is_authenticated:
bookmark_id = kwargs.get('bookmark')
bookmark = Bookmark.objects.get(id=bookmark_id)
if bookmark.category.user == request.user:
--- a/src/requirements/base.txt Thu Oct 12 17:33:22 2017 +0200
+++ b/src/requirements/base.txt Mon May 14 14:45:22 2018 +0200
@@ -1,19 +1,11 @@
-appdirs==1.4.3
-Django==1.10.5
-django-comments-xtd==1.6.3
-django-contrib-comments==1.7.3
-django-haystack==2.6.0
-django-model-utils==2.6.1
-django-notifications-hq==1.2
-djangorestframework==3.5.4
-elasticsearch==5.1.0
-jsonfield==1.0.3
-olefile==0.44
-packaging==16.8
-Pillow==4.0.0
-pyparsing==2.1.10
-pytz==2016.10
-requests==2.13.0
-six==1.10.0
-sorl-thumbnail==12.4a1
-urllib3==1.20
+Django==2.0.5
+django-comments-xtd==2.1.0
+django-contrib-comments==1.8.0
+django-haystack==2.8.1
+#django-notifications-hq==1.4.0a0
+git+https://github.com/django-notifications/django-notifications.git#egg=django-notifications-hq
+djangorestframework==3.8.2
+elasticsearch==6.2.0
+Pillow==5.1.0
+requests==2.18.4
+sorl-thumbnail==12.4.1
--- a/src/requirements/dev.txt Thu Oct 12 17:33:22 2017 +0200
+++ b/src/requirements/dev.txt Mon May 14 14:45:22 2018 +0200
@@ -1,1 +1,2 @@
-r base.txt
+setuptools_scm
--- a/src/requirements/prod.txt Thu Oct 12 17:33:22 2017 +0200
+++ b/src/requirements/prod.txt Mon May 14 14:45:22 2018 +0200
@@ -1,4 +1,4 @@
-r base.txt
pylibmc
uWSGI
-psycopg2
+psycopg2 --no-binary psycopg2
--- a/src/setup.py Thu Oct 12 17:33:22 2017 +0200
+++ b/src/setup.py Mon May 14 14:45:22 2018 +0200
@@ -120,8 +120,9 @@
'Programming Language :: Python',
'Topic :: Utilities'
],
+ setup_requires=['setuptools_scm'],
install_requires=[
- "Django >= 1.9",
+ "Django >= 2.0",
"django-comments-xtd",
"django-contrib-comments",
"django-haystack",
@@ -132,8 +133,8 @@
"pytz",
"requests",
"six",
- "sorl-thumbnail >= 12.4a1",
- "djangorestframework >= 3.5"
+ "sorl-thumbnail >= 12.4.1",
+ "djangorestframework >= 3.8"
],
)