--- a/src/iconolab/management/commands/importimages.py Fri Aug 26 13:36:05 2016 +0200
+++ b/src/iconolab/management/commands/importimages.py Mon Aug 29 16:19:16 2016 +0200
@@ -8,15 +8,22 @@
class Command(BaseCommand):
help = "import images from a directory into the media folder and creates item and image objects"
-
+
def add_arguments(self, parser):
parser.add_argument("csv_path")
parser.add_argument(
+ '--jpeg-quality',
+ dest='jpeg_quality',
+ default=settings.IMG_JPG_DEFAULT_QUALITY,
+ help='Jpeg default quality'
+
+ )
+ parser.add_argument(
'--encoding',
dest='encoding',
default='utf-8',
help='CSV file encoding'
-
+
)
parser.add_argument(
'--collection-fixture',
@@ -36,7 +43,13 @@
default=False,
help='add metacategories to the created collection from a fixture file',
)
-
+ parser.add_argument(
+ '--delimiter',
+ dest='csv_delimiter',
+ default=';',
+ help='csv file delimiter'
+ )
+
def handle(self, *args, **options):
pp = pprint.PrettyPrinter(indent=4)
try:
@@ -57,7 +70,7 @@
if collection_data[0]["model"] != "iconolab.Collection":
raise ValueError("!!! Collection fixture should provide one iconolab.Collection object and nothing else. !!!")
except ValueError as e:
- raise ValueError("!!! JSON Data is invalid. !!!")
+ raise ValueError("!!! JSON Data is invalid. !!!")
elif options.get("collection_id"):
print("## Finding collection with id "+options.get("collection_id"))
try:
@@ -65,8 +78,8 @@
except Collection.DoesNotExist:
raise ValueError("!!! Collection with primary key "+options.get("collection_id")+" was not found, aborting !!!")
else:
- raise ValueError("!!! No collection fixture or collection id, aborting because we can't properly generate data. !!!")
-
+ raise ValueError("!!! No collection fixture or collection id, aborting because we can't properly generate data. !!!")
+
if options.get("metacategories_fixture"):
print("## Finding metacategories fixture json data in "+source_dir)
metacategories_fixture_path = os.path.join(source_dir, options.get("metacategories_fixture"))
@@ -81,9 +94,9 @@
raise ValueError("!!! The fixture should only contain metacategories for the imported collection !!!")
elif options.get("collection_id") and metacategory["fields"].get("collection", False) != collection.id:
raise ValueError("!!! The fixture should only contain metacategories for the imported collection !!!")
-
+
# We read the csv
- csvreader = csv.DictReader(open(options.get("csv_path"), encoding=options.get("encoding")), delimiter=";")
+ csvreader = csv.DictReader(open(options.get("csv_path"), encoding=options.get("encoding")), delimiter=options.get('csv_delimiter', ';'))
print("# Extracting data from csv file and storing it in standardized format")
# We store data using the Jocondelab keys, as defined in settings.IMPORT_FIELDS_DICT
cleaned_csv_data=[]
@@ -96,7 +109,7 @@
cleaned_row_data[key] = row[row_key]
break
cleaned_csv_data.append(cleaned_row_data)
-
+
print("# Finding corresponding images and filtering csv data for found images")
# Listing image files in csv directory
image_list = [f for f in os.listdir(source_dir) if os.path.isfile(os.path.join(source_dir, f)) and not f.endswith(".csv")]
@@ -128,7 +141,7 @@
col_im = ImagePIL.open(os.path.join(source_dir, collection_image_name))
print("##### Generating or copying jpeg for "+collection_image_name)
col_im.thumbnail(col_im.size)
- col_im.save(collection_image_path, "JPEG", quality=100)
+ col_im.save(collection_image_path, "JPEG", quality=options.get("jpeg_quality", settings.IMG_JPG_DEFAULT_QUALITY))
except Exception as e:
print(e)
if options.get("metacategories_fixture"):
@@ -138,6 +151,9 @@
print("### Images will be stored in "+target_dir)
for item in filtered_csv_data:
print("#### Computing metadatas for item "+item["INV"]+" (inv number)")
+ if not item["INV"]:
+ print("#### No INV number, skipping")
+ continue
item_authors = item["AUTR"]
item_school = item["ECOLE"]
item_designation = ""
@@ -195,16 +211,18 @@
im_width, im_height = im.size
except Exception as e:
print(e)
+ continue
else:
jpeg_img_path = image_path
try:
im = ImagePIL.open(os.path.join(source_dir, image))
print("##### Generating or copying jpeg for "+image)
im.thumbnail(im.size)
- im.save(jpeg_img_path, "JPEG", quality=100)
+ im.save(jpeg_img_path, "JPEG", quality=options.get("jpeg_quality", settings.IMG_JPG_DEFAULT_QUALITY))
im_width, im_height = im.size
except Exception as e:
print(e)
+ continue
new_image = Image.objects.create(
item = item_object,
media = "uploads/"+image_name+".jpg",
@@ -220,4 +238,3 @@
print("!!! File "+options.get("csv_path")+" does not exist. !!!")
except ValueError as e:
print(str(e))
-
\ No newline at end of file
--- a/src/iconolab/settings/__init__.py Fri Aug 26 13:36:05 2016 +0200
+++ b/src/iconolab/settings/__init__.py Mon Aug 29 16:19:16 2016 +0200
@@ -10,7 +10,7 @@
https://docs.djangoproject.com/en/1.9/ref/settings/
"""
-import os, logging
+import os, logging, sys
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@@ -223,3 +223,7 @@
}
NO_IMG_CONVERSION_EXTS = [".jpg"]
IMG_CONVERSION_EXTS = [".tif", ".tiff"]
+
+IMG_JPG_DEFAULT_QUALITY = 80
+
+DJANGO_RUNSERVER = (sys.argv[1] == 'runserver')
--- a/src/iconolab/settings/dev.py.tmpl Fri Aug 26 13:36:05 2016 +0200
+++ b/src/iconolab/settings/dev.py.tmpl Mon Aug 29 16:19:16 2016 +0200
@@ -1,266 +1,250 @@
-"""
-Django settings for iconolab project.
-
-Generated by 'django-admin startproject' using Django 1.9.5.
-
-For more information on this file, see
-https://docs.djangoproject.com/en/1.9/topics/settings/
-
-For the full list of settings and their values, see
-https://docs.djangoproject.com/en/1.9/ref/settings/
-"""
-
-import os
-
-# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
-BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-
-STATIC_ROOT = os.path.join(BASE_DIR, '../../web/static/site')
-MEDIA_ROOT = os.path.join(BASE_DIR, '../../web/media')
-
-# dev_mode useful for src_js
-# We need to add 'iconolab.utils.context_processors.env' to context processor
-
-SRC_JS_PATH = os.path.join(BASE_DIR, '..', '..', 'src_js')
-DEV_MODE = True
-
-STATICFILES_DIRS = [
- os.path.join(BASE_DIR, 'static'),
- os.path.join(BASE_DIR, 'media'),
- SRC_JS_PATH,
-]
-
-
-
-STATICFILES_DIRS = [
- os.path.join(BASE_DIR, 'static'),
-]
-BASE_URL = ''
-STATIC_URL = '/static/'
-MEDIA_URL = '/media/'
-
-LOGIN_URL = '/account/login/'
-
-# Quick-start development settings - unsuitable for production
-# See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/
-
-# SECURITY WARNING: keep the secret key used in production secret!
-SECRET_KEY = '#8)+upuo3vc7fi15czxz53ml7*(1__q8hg=m&+9ylq&st1_kqv'
-
-# SECURITY WARNING: don't run with debug turned on in production!
-DEBUG = True
-THUMBNAIL_DEBUG = True
-
-ALLOWED_HOSTS = []
-
-
-# Application definition
-
-INSTALLED_APPS = [
- 'django.contrib.admin',
- 'django.contrib.auth',
- 'django.contrib.contenttypes',
- 'django.contrib.sessions',
- 'django.contrib.messages',
- 'django.contrib.staticfiles',
- 'django.contrib.sites',
- 'django_comments',
- 'django_comments_xtd',
- 'haystack',
- 'iconolab.apps.IconolabApp',
- 'sorl.thumbnail',
- 'notifications'
-]
-
-
-
-COMMENTS_APP = "django_comments_xtd"
-COMMENTS_XTD_MODEL = "iconolab.models.IconolabComment"
-COMMENTS_XTD_FORM_CLASS = 'iconolab.forms.comments.IconolabCommentForm'
-COMMENTS_XTD_MAX_THREAD_LEVEL = 100
-COMMENTS_PER_PAGE_DEFAULT = 10
-
-SITE_ID = 1
-
-MIDDLEWARE_CLASSES = [
- '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',
- 'reversion.middleware.RevisionMiddleware',
-]
-
-STATICFILES_DIRS = [
- os.path.join(BASE_DIR, 'static'),
- os.path.join(BASE_DIR, 'iconolab', 'media'),
-]
-
-MEDIA_URL = os.path.join(BASE_DIR, 'iconolab', 'media') + "/"
-
-ROOT_URLCONF = 'iconolab.urls'
-
-TEMPLATES = [
- {
- 'BACKEND': 'django.template.backends.django.DjangoTemplates',
- 'DIRS': [os.path.join(BASE_DIR,'iconolab','templates')],
- 'APP_DIRS': True,
- 'OPTIONS': {
- 'context_processors': [
- 'django.template.context_processors.debug',
- 'django.template.context_processors.request',
- 'django.contrib.auth.context_processors.auth',
- 'django.contrib.messages.context_processors.messages',
- 'django.core.context_processors.media',
- 'django.core.context_processors.static',
- 'django.core.context_processors.i18n',
- 'iconolab.utils.context_processors.env',
- ],
- },
- },
-]
-
-WSGI_APPLICATION = 'iconolab.wsgi.application'
-
-
-# Database
-# https://docs.djangoproject.com/en/1.9/ref/settings/#databases
-
-DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.sqlite3',
- 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
- }
-}
-
-# Logging
-
-LOG_FILE = os.path.abspath(os.path.join(BASE_DIR,"../../run/log/log.txt"))
-LOG_LEVEL = logging.DEBUG
-LOGGING = {
- 'version': 1,
- 'disable_existing_loggers': True,
- 'filters': {
- 'require_debug_false': {
- '()': 'django.utils.log.RequireDebugFalse'
- }
- },
- 'formatters' : {
- 'simple' : {
- 'format': "%(asctime)s - %(levelname)s : %(message)s",
- },
- 'semi-verbose': {
- 'format': '%(levelname)s %(asctime)s %(module)s %(message)s'
- },
- },
- 'handlers': {
- 'mail_admins': {
- 'level': 'ERROR',
- 'filters': ['require_debug_false'],
- 'class': 'django.utils.log.AdminEmailHandler'
- },
- 'stream_to_console': {
- 'level': LOG_LEVEL,
- 'class': 'logging.StreamHandler'
- },
- 'file': {
- 'level': LOG_LEVEL,
- 'class': 'logging.FileHandler',
- 'filename': LOG_FILE,
- 'formatter': 'semi-verbose',
- },
- },
- 'loggers': {
- 'django.request': {
- 'handlers': ['file'],
- 'level': LOG_LEVEL,
- 'propagate': True,
- },
- 'iconolab': {
- 'handlers': ['file'],
- 'level': LOG_LEVEL,
- 'propagate': True,
- },
- }
-}
-
-
-# Haystack connection
-HAYSTACK_CONNECTIONS = {
- 'default': {
- 'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine',
- 'URL': 'http://127.0.0.1:9200/',
- 'INDEX_NAME': 'haystack',
- },
-}
-
-# HAYSTACK_SIGNAL_PROCESSOR
-HAYSTACK_SIGNAL_PROCESSOR = 'iconolab.search_indexes.signals.RevisionSignalProcessor'
-
-CACHES = {
- 'default': {
- 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
- 'LOCATION': os.path.join(MEDIA_ROOT, 'cache'),
-# 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
-# 'LOCATION': 'unix:/var/run/memcached/memcached.socket',
-# 'KEY_PREFIX': 'ldt',
- }
-}
-# Password validation
-# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators
-
-AUTH_PASSWORD_VALIDATORS = [
- {
- 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
- },
- {
- 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
- },
- {
- 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
- },
- {
- 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
- },
-]
-
-
-# Internationalization
-# https://docs.djangoproject.com/en/1.9/topics/i18n/
-
-LANGUAGE_CODE = 'en-us'
-
-TIME_ZONE = 'UTC'
-
-USE_I18N = True
-
-USE_L10N = True
-
-USE_TZ = True
-
-
-IMPORT_FIELDS_DICT = {
- "AUTR": [],
- "ECOLE": [],
- "TITR": ["Titre"],
- "DENO": [],
- "APPL": [],
- "PERI": ["Période"],
- "MILL": [],
- "EPOCH": [],
- "TECH": [],
- "DIMS": ["Dimensions"],
- "EPOCH": [],
- "LIEUX": [],
- "DECV": [],
- "LOCA": ["Localisation"],
- "PHOT": ["Photo"],
- "INV": ["No inventaire",],
- "REF": ["REFERENCE"],
-}
-
-INTERNAL_TAGS_URL = BASE_URL
-JOCONDE_NOTICE_BASE_URL = "http://www.culture.gouv.fr/public/mistral/joconde_fr?ACTION=CHERCHER&FIELD_98=REF&VALUE_98="
+"""
+Django settings for iconolab project.
+
+Generated by 'django-admin startproject' using Django 1.9.5.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/1.9/topics/settings/
+
+For the full list of settings and their values, see
+https://docs.djangoproject.com/en/1.9/ref/settings/
+"""
+from iconolab.settings import *
+
+import os, logging
+
+# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
+BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+
+STATIC_ROOT = os.path.join(BASE_DIR, '../../web/static/site')
+MEDIA_ROOT = os.path.join(BASE_DIR, '../../web/media')
+
+# dev_mode useful for src_js
+# We need to add 'iconolab.utils.context_processors.env' to context processor
+
+SRC_JS_PATH = os.path.join(BASE_DIR, '..', '..', 'src_js')
+DEV_MODE = True
+
+BASE_URL = ''
+STATIC_URL = '/static/'
+MEDIA_URL = '/media/'
+
+LOGIN_URL = '/account/login/'
+
+# Quick-start development settings - unsuitable for production
+# See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/
+
+# SECURITY WARNING: keep the secret key used in production secret!
+SECRET_KEY = '#8)+upuo3vc7fi15czxz53ml7*(1__q8hg=m&+9ylq&st1_kqv'
+
+# SECURITY WARNING: don't run with debug turned on in production!
+DEBUG = True
+THUMBNAIL_DEBUG = True
+
+ALLOWED_HOSTS = []
+
+
+# Application definition
+
+INSTALLED_APPS = [
+ 'django.contrib.admin',
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.messages',
+ 'django.contrib.staticfiles',
+ 'django.contrib.sites',
+ 'django_comments',
+ 'django_comments_xtd',
+ 'haystack',
+ 'iconolab.apps.IconolabApp',
+ 'sorl.thumbnail',
+ 'notifications'
+]
+
+
+
+COMMENTS_APP = "django_comments_xtd"
+COMMENTS_XTD_MODEL = "iconolab.models.IconolabComment"
+COMMENTS_XTD_FORM_CLASS = 'iconolab.forms.comments.IconolabCommentForm'
+COMMENTS_XTD_MAX_THREAD_LEVEL = 100
+COMMENTS_PER_PAGE_DEFAULT = 10
+
+SITE_ID = 1
+
+MIDDLEWARE_CLASSES = [
+ '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',
+ 'reversion.middleware.RevisionMiddleware',
+]
+
+
+ROOT_URLCONF = 'iconolab.urls'
+
+TEMPLATES = [
+ {
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
+ 'DIRS': [os.path.join(BASE_DIR,'iconolab','templates')],
+ 'APP_DIRS': True,
+ 'OPTIONS': {
+ 'context_processors': [
+ 'django.template.context_processors.debug',
+ 'django.template.context_processors.request',
+ 'django.contrib.auth.context_processors.auth',
+ 'django.contrib.messages.context_processors.messages',
+ 'django.core.context_processors.media',
+ 'django.core.context_processors.static',
+ 'django.core.context_processors.i18n',
+ 'iconolab.utils.context_processors.env',
+ ],
+ },
+ },
+]
+
+WSGI_APPLICATION = 'iconolab.wsgi.application'
+
+
+# Database
+# https://docs.djangoproject.com/en/1.9/ref/settings/#databases
+
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.sqlite3',
+ 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
+ }
+}
+
+# Logging
+
+LOG_FILE = os.path.abspath(os.path.join(BASE_DIR,"../../run/log/log.txt"))
+LOG_LEVEL = logging.DEBUG
+LOGGING = {
+ 'version': 1,
+ 'disable_existing_loggers': True,
+ 'filters': {
+ 'require_debug_false': {
+ '()': 'django.utils.log.RequireDebugFalse'
+ }
+ },
+ 'formatters' : {
+ 'simple' : {
+ 'format': "%(asctime)s - %(levelname)s : %(message)s",
+ },
+ 'semi-verbose': {
+ 'format': '%(levelname)s %(asctime)s %(module)s %(message)s'
+ },
+ },
+ 'handlers': {
+ 'mail_admins': {
+ 'level': 'ERROR',
+ 'filters': ['require_debug_false'],
+ 'class': 'django.utils.log.AdminEmailHandler'
+ },
+ 'stream_to_console': {
+ 'level': LOG_LEVEL,
+ 'class': 'logging.StreamHandler'
+ },
+ 'file': {
+ 'level': LOG_LEVEL,
+ 'class': 'logging.FileHandler',
+ 'filename': LOG_FILE,
+ 'formatter': 'semi-verbose',
+ },
+ },
+ 'loggers': {
+ 'django.request': {
+ 'handlers': ['file'],
+ 'level': LOG_LEVEL,
+ 'propagate': True,
+ },
+ 'iconolab': {
+ 'handlers': ['file'],
+ 'level': LOG_LEVEL,
+ 'propagate': True,
+ },
+ }
+}
+
+
+# Haystack connection
+HAYSTACK_CONNECTIONS = {
+ 'default': {
+ 'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine',
+ 'URL': 'http://127.0.0.1:9200/',
+ 'INDEX_NAME': 'haystack',
+ },
+}
+
+# HAYSTACK_SIGNAL_PROCESSOR
+HAYSTACK_SIGNAL_PROCESSOR = 'iconolab.search_indexes.signals.RevisionSignalProcessor'
+
+CACHES = {
+ 'default': {
+ 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
+ 'LOCATION': os.path.join(MEDIA_ROOT, 'cache'),
+# 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
+# 'LOCATION': 'unix:/var/run/memcached/memcached.socket',
+# 'KEY_PREFIX': 'ldt',
+ }
+}
+# Password validation
+# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators
+
+AUTH_PASSWORD_VALIDATORS = [
+ {
+ 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
+ },
+ {
+ 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
+ },
+ {
+ 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
+ },
+ {
+ 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
+ },
+]
+
+
+# Internationalization
+# https://docs.djangoproject.com/en/1.9/topics/i18n/
+
+LANGUAGE_CODE = 'en-us'
+
+TIME_ZONE = 'UTC'
+
+USE_I18N = True
+
+USE_L10N = True
+
+USE_TZ = True
+
+
+IMPORT_FIELDS_DICT = {
+ "AUTR": [],
+ "ECOLE": [],
+ "TITR": ["Titre"],
+ "DENO": [],
+ "APPL": [],
+ "PERI": ["Période"],
+ "MILL": [],
+ "EPOCH": [],
+ "TECH": [],
+ "DIMS": ["Dimensions"],
+ "EPOCH": [],
+ "LIEUX": [],
+ "DECV": [],
+ "LOCA": ["Localisation"],
+ "PHOT": ["Photo"],
+ "INV": ["No inventaire",],
+ "REF": ["REFERENCE"],
+}
+
+INTERNAL_TAGS_URL = BASE_URL
+JOCONDE_NOTICE_BASE_URL = "http://www.culture.gouv.fr/public/mistral/joconde_fr?ACTION=CHERCHER&FIELD_98=REF&VALUE_98="
--- a/src/iconolab/templates/iconolab/home.html Fri Aug 26 13:36:05 2016 +0200
+++ b/src/iconolab/templates/iconolab/home.html Mon Aug 29 16:19:16 2016 +0200
@@ -35,9 +35,11 @@
{% block footer_js %}
<script>
- $(".collection-container:not(.selected)").hide();
- var selectedID = /collection\-panel\-([0-9a-z\-]+)/.exec($(".collection-container.selected").attr("id"))[1];
- $(".btn-collection").on("click", function(e){
+ $(".collection-container:not(.selected)").hide();
+ var selectedContainerId = $(".collection-container.selected").attr("id");
+ if(selectedContainerId) {
+ var selectedID = /collection\-panel\-([0-9a-z\-]+)/.exec($(".collection-container.selected").attr("id"))[1];
+ $(".btn-collection").on("click", function(e){
selectedID = /show\-collection\-([0-9a-z\-]+)/.exec($(this).attr("id"))[1];
if (!$(this).hasClass("btn-primary")){
$(".collection-container").removeClass("selected");
@@ -47,6 +49,8 @@
$(".collection-container#collection-panel-"+selectedID).show()
$(".collection-container#collection-panel-"+selectedID).addClass("selected")
}
- })
+ });
+ }
+
</script>
-{% endblock %}
\ No newline at end of file
+{% endblock %}
--- a/src/iconolab/urls.py Fri Aug 26 13:36:05 2016 +0200
+++ b/src/iconolab/urls.py Mon Aug 29 16:19:16 2016 +0200
@@ -20,7 +20,7 @@
from django import views as django_views
from iconolab import views
from iconolab.search_indexes.views import IconolabSearchView
-from . import settings
+from django.conf import settings
from django.conf.urls.static import static
from django.contrib.auth.decorators import login_required
@@ -51,7 +51,7 @@
url(r'^comments/', include('django_comments_xtd.urls')),
url(r'^comments/annotation/post', views.comments.post_comment_iconolab, name="post_comment"),
url('^user/notifications/', include(notifications.urls, namespace='notifications')),
-
+
url(r'collections/(?P<collection_name>[a-z0-9\-]+)/search/(?P<model_type>[a-z0-9\-]+)', IconolabSearchView.as_view(), name="collection_with_model_search"),
url(r'^search/(?P<model_type>[a-z0-9\-]+)', IconolabSearchView.as_view(), name="model_search"),
@@ -62,7 +62,9 @@
#url(r'^search/', include('haystack.urls'), name="search_iconolab"),
]
-urlpatterns += staticfiles_urlpatterns()
-urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
-#static url
-urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
+
+if settings.DJANGO_RUNSERVER:
+ urlpatterns += staticfiles_urlpatterns()
+ urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
+ #static url
+ urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
--- a/src/iconolab/views/iconolab.py Fri Aug 26 13:36:05 2016 +0200
+++ b/src/iconolab/views/iconolab.py Mon Aug 29 16:19:16 2016 +0200
@@ -26,7 +26,7 @@
class TestView(View):
template_name = "iconolab/compare.html"
-
+
def get(self, request, *args, **kwargs):
return render(request, self.template_name)
@@ -35,37 +35,37 @@
class UserHomeView(DetailView):
model = User
slug_field = 'id'
-
+
def get_context_data(self, **kwargs):
context = super(UserHomeView, self).get_context_data(**kwargs)
return context
-
+
def get(self, request, *args, **kwargs):
self.object = self.get_object()
context = self.get_context_data()
profile_user = self.object
context['profile_user'] = profile_user
context['user_annotations'] = Annotation.objects.filter(author=profile_user).prefetch_related(
- 'current_revision',
- 'revisions',
- 'image',
- 'image__item',
+ 'current_revision',
+ 'revisions',
+ 'image',
+ 'image__item',
'image__item__collection'
)
context['user_revisions_annotations'] = Annotation.objects.filter(revisions__author=profile_user).exclude(author=profile_user).prefetch_related(
- 'current_revision',
- 'revisions',
- 'image',
- 'image__item',
+ 'current_revision',
+ 'revisions',
+ 'image',
+ 'image__item',
'image__item__collection'
).distinct()
comments_annotations_str_id = IconolabComment.objects.filter(user=profile_user, content_type__app_label='iconolab', content_type__model='annotation').values_list('object_pk', flat=True)
comments_annotations_id = [int(str_id) for str_id in comments_annotations_str_id]
context['user_comments_annotations'] = Annotation.objects.filter(id__in=comments_annotations_id).exclude(author=profile_user).exclude(annotation_guid__in=context['user_revisions_annotations'].values_list('annotation_guid', flat=True)).prefetch_related(
- 'current_revision',
- 'revisions',
- 'image',
- 'image__item',
+ 'current_revision',
+ 'revisions',
+ 'image',
+ 'image__item',
'image__item__collection'
).distinct()
if request.user.is_authenticated() and self.object == request.user:
@@ -75,7 +75,7 @@
return render(request, 'iconolab/user_home.html', context)
class UserNotificationsView(View):
-
+
def get(self, request, *args, **kwargs):
context = {}
notifications = Notification.objects.filter(recipient=request.user)
@@ -98,6 +98,7 @@
Returns a boolean depending on wether (True) or not (False) the objects were found and a tuple containing the objects, with a select_related/prefetch_related on relevant related objects
following this ordering: (collection, item, image, annotation, revision)
'''
+
objects_tuple = ()
if 'collection_name' in kwargs.keys():
try:
@@ -136,30 +137,30 @@
context = super(CollectionHomepageView, self).get_context_data(**kwargs)
context['collection_name'] = self.kwargs.get('collection_name', '')
context['collection'] = collection
-
+
# Recent annotations
context['recent_annotations'] = Annotation.objects.filter(image__item__collection__name=collection.name).prefetch_related(
- 'current_revision',
+ 'current_revision',
'stats'
).order_by('-current_revision__created')
-
+
# Recent annotations
context['revised_annotations'] = Annotation.objects.filter(image__item__collection__name=collection.name).prefetch_related(
- 'current_revision',
+ 'current_revision',
'stats'
).annotate(revision_count=Count("revisions")).order_by('-revision_count')
-
+
contrib_calls_annotations_ids = list(set(MetaCategoryInfo.objects.filter(
- metacategory__collection__name=collection.name,
+ metacategory__collection__name=collection.name,
metacategory__triggers_notifications=MetaCategory.CONTRIBUTORS
).order_by("comment__submit_date").values_list("comment__object_pk", flat=True)))
-
+
collection_annotations = Annotation.objects.filter(id__in=contrib_calls_annotations_ids).all()
collection_ann_dict = dict([(str(annotation.id), annotation) for annotation in collection_annotations])
context["contribution_calls_annotations_list"] = [collection_ann_dict[id] for id in contrib_calls_annotations_ids]
-
+
return render(request, 'iconolab/collection_home.html', context)
-
+
class ShowItemView(View, ContextMixin, IconolabObjectView):
@@ -192,15 +193,15 @@
context['collection'] = collection
context['image'] = image
return render(request, 'iconolab/detail_image.html', context)
-
+
class CreateAnnotationView(View, ContextMixin, IconolabObjectView):
-
+
def get_context_data(self, **kwargs):
context = super(CreateAnnotationView, self).get_context_data(**kwargs)
context['collection_name'] = self.kwargs.get('collection_name', '')
context['image_guid'] = self.kwargs.get('image_guid', '')
return context
-
+
def get(self, request, *args, **kwargs):
success, result = self.check_kwargs(kwargs)
if success:
@@ -212,8 +213,8 @@
context['image'] = image
context['form'] = annotation_form
context['tags_data'] = '[]'
- return render(request, 'iconolab/change_annotation.html', context)
-
+ return render(request, 'iconolab/change_annotation.html', context)
+
def post(self, request, *args, **kwargs):
success, result = self.check_kwargs(kwargs)
if success:
@@ -249,7 +250,7 @@
render(request, 'iconolab/change_annotation.html', context)
class ShowAnnotationView(View, ContextMixin, IconolabObjectView):
-
+
def get_context_data(self, **kwargs):
context = super(ShowAnnotationView, self).get_context_data(**kwargs)
context['collection_name'] = self.kwargs.get('collection_name', '')
@@ -268,7 +269,7 @@
context['image'] = image
context['annotation'] = annotation
context['tags_data'] = annotation.current_revision.get_tags_json()
-
+
page = request.GET.get('page', 1)
per_page = request.GET.get('perpage', 10)
full_comments_list = IconolabComment.objects.for_app_models('iconolab.annotation').filter(object_pk = annotation.pk).order_by('thread_id', '-order')
@@ -280,12 +281,12 @@
except EmptyPage:
comments_list = paginator.page(paginator.num_pages)
context['comments'] = comments_list
-
+
if request.user.is_authenticated():
user_comment_notifications = Notification.objects.filter(
- recipient=request.user,
- action_object_content_type__app_label='iconolab',
- action_object_content_type__model='iconolabcomment',
+ recipient=request.user,
+ action_object_content_type__app_label='iconolab',
+ action_object_content_type__model='iconolabcomment',
target_content_type__app_label='iconolab',
target_content_type__model='annotation',
target_object_id=annotation.id
@@ -295,7 +296,7 @@
for notification in user_comment_notifications.all():
if int(notification.action_object_object_id) in comment_list_ids:
notification.mark_as_read()
-
+
image.stats.views_count += 1
image.stats.save()
annotation.stats.views_count += 1
@@ -304,14 +305,14 @@
class EditAnnotationView(View, ContextMixin, IconolabObjectView):
-
+
def get_context_data(self, **kwargs):
context = super(EditAnnotationView, self).get_context_data(**kwargs)
context['collection_name'] = self.kwargs.get('collection_name', '')
context['image_guid'] = self.kwargs.get('image_guid', '')
context['annotation_guid'] = self.kwargs.get('annotation_guid', '')
return context
-
+
def get(self, request, *args, **kwargs):
success, result = self.check_kwargs(kwargs)
if success:
@@ -324,8 +325,8 @@
context['annotation'] = annotation
context['form'] = annotation_form
context['tags_data'] = annotation.current_revision.get_tags_json()
- return render(request, 'iconolab/change_annotation.html', context)
-
+ return render(request, 'iconolab/change_annotation.html', context)
+
def post(self, request, *args, **kwargs):
success, result = self.check_kwargs(kwargs)
if success:
@@ -364,7 +365,7 @@
class ShowRevisionView(View, ContextMixin, IconolabObjectView):
-
+
def get_context_data(self, **kwargs):
context = super(ShowRevisionView, self).get_context_data(**kwargs)
context['collection_name'] = self.kwargs.get('collection_name', '')
@@ -372,7 +373,7 @@
context['annotation_guid'] = self.kwargs.get('annotation_guid', '')
context['revision_guid'] = self.kwargs.get('revision_guid', '')
return context
-
+
def get(self, request, *args, **kwargs):
success, result = self.check_kwargs(kwargs)
if success:
@@ -388,8 +389,8 @@
context['comment'] = revision.creation_comment.first()
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',
+ recipient=request.user,
+ action_object_content_type__app_label='iconolab',
action_object_content_type__model='annotationrevision',
action_object_object_id=revision.id,
target_content_type__app_label='iconolab',
@@ -401,8 +402,8 @@
context['notified_revision'] = True
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',
+ recipient=request.user,
+ action_object_content_type__app_label='iconolab',
action_object_content_type__model='annotationrevision',
action_object_object_id=revision.id,
target_content_type__app_label='iconolab',
@@ -414,9 +415,9 @@
context['notified_revision'] = True
return render(request, 'iconolab/detail_revision.html', context)
-
+
class MergeProposalView(View, ContextMixin, IconolabObjectView):
-
+
def get_context_data(self, **kwargs):
context = super(MergeProposalView, self).get_context_data(**kwargs)
context['collection_name'] = self.kwargs.get('collection_name', '')
@@ -434,10 +435,10 @@
# Only show merge form if there is a revision to merge AND the current user is the annotation author
if revision.state != AnnotationRevision.AWAITING or request.user != annotation.author:
return RedirectView.as_view(
- url=reverse('revision_detail',
+ url=reverse('revision_detail',
kwargs={
- 'collection_name': collection.name,
- 'image_guid': image.image_guid,
+ 'collection_name': collection.name,
+ 'image_guid': image.image_guid,
'annotation_guid': annotation.annotation_guid,
'revision_guid': revision.revision_guid
}
@@ -447,27 +448,27 @@
if 'auto_accept' in request.GET and request.GET['auto_accept'] in ['True', 'true', '1', 'yes'] and revision.parent_revision == annotation.current_revision:
annotation.validate_existing_revision(revision)
return RedirectView.as_view(
- url=reverse('annotation_detail',
+ url=reverse('annotation_detail',
kwargs={
- 'collection_name': collection.name,
- 'image_guid': image.image_guid,
+ 'collection_name': collection.name,
+ 'image_guid': image.image_guid,
'annotation_guid': annotation.annotation_guid
}
)
)(request)
# Auto-reject the revision only if the proper query arg is set
if 'auto_reject' in request.GET and request.GET['auto_reject'] in ['True', 'true', '1', 'yes']:
- annotation.reject_existing_revision(revision)
+ annotation.reject_existing_revision(revision)
return RedirectView.as_view(
- url=reverse('annotation_detail',
+ url=reverse('annotation_detail',
kwargs={
- 'collection_name': collection.name,
- 'image_guid': image.image_guid,
+ 'collection_name': collection.name,
+ 'image_guid': image.image_guid,
'annotation_guid': annotation.annotation_guid
}
)
)(request)
-
+
context = self.get_context_data(**kwargs)
context['collection'] = collection
context['image'] = image
@@ -484,11 +485,11 @@
context['current_revision'] = annotation.current_revision
context['current_tags_data'] = annotation.current_revision.get_tags_json()
context['current_comment'] = annotation.current_revision.creation_comment.first()
-
+
merge_form = AnnotationRevisionForm(instance=revision)
context['merge_form'] = merge_form
return render(request, 'iconolab/merge_revision.html', context)
-
+
def post(self, request, *args, **kwargs):
# Handle merge form submit here
success, result = self.check_kwargs(kwargs)
@@ -500,7 +501,7 @@
image_guid = kwargs['image_guid']
annotation_guid = kwargs['annotation_guid']
revision_guid = kwargs['revision_guid']
-
+
merge_revision_form = AnnotationRevisionForm(request.POST)
if merge_revision_form.is_valid():
revision_title = merge_revision_form.cleaned_data['title']
@@ -537,10 +538,10 @@
context['current_tags_data'] = annotation.current_revision.get_tags_json()
context['current_comment'] = annotation.current_revision.creation_comment.first()
return render(request, 'iconolab/merge_revision.html', context)
-
-
+
+
class NotFoundErrorView(TemplateView):
template_name='errors/404error.html'
-
+
class HelpView(TemplateView):
- template_name='iconolab/glossary.html'
\ No newline at end of file
+ template_name='iconolab/glossary.html'
--- a/src/requirements/base.txt Fri Aug 26 13:36:05 2016 +0200
+++ b/src/requirements/base.txt Mon Aug 29 16:19:16 2016 +0200
@@ -11,5 +11,5 @@
pytz==2016.6.1
requests==2.11.1
six==1.10.0
-sorl-thumbnail==12.3
+sorl-thumbnail==12.4a1
urllib3==1.16
--- a/src/requirements/base.txt.in Fri Aug 26 13:36:05 2016 +0200
+++ b/src/requirements/base.txt.in Mon Aug 29 16:19:16 2016 +0200
@@ -1,13 +1,13 @@
-Django >= 1.9
-django-comments-xtd
-django-contrib-comments
-django-haystack
-django-notifications-hq
-elasticsearch
-jsonfield
-Pillow
-psycopg2
-pytz
-requests
-six
-sorl-thumbnail
+Django >= 1.9
+django-comments-xtd
+django-contrib-comments
+django-haystack
+django-notifications-hq
+elasticsearch
+jsonfield
+Pillow
+psycopg2
+pytz
+requests
+six
+sorl-thumbnail >= 12.4a1