diff --git a/media/admin.py b/media/admin.py
index 69d603d..bbc06d2 100644
--- a/media/admin.py
+++ b/media/admin.py
@@ -8,6 +8,7 @@ from django.utils.translation import ugettext_lazy as _
from reversion.admin import VersionAdmin
from med.admin import admin_site
+from .forms import MediaAdminForm
from .models import Auteur, Emprunt, Jeu, Media
@@ -17,16 +18,43 @@ class AuteurAdmin(VersionAdmin):
class MediaAdmin(VersionAdmin):
- list_display = ('title', 'authors_list', 'side_title', 'isbn')
+ list_display = ('title', 'authors_list', 'side_title', 'isbn',
+ 'external_link')
search_fields = ('title', 'authors__nom', 'side_title', 'subtitle', 'isbn')
autocomplete_fields = ('authors',)
date_hierarchy = 'publish_date'
+ form = MediaAdminForm
def authors_list(self, obj):
return ", ".join([a.nom for a in obj.authors.all()])
authors_list.short_description = _('authors')
+ def external_link(self, obj):
+ return format_html('{}',
+ obj.external_url, obj.external_url)
+
+ external_link.allow_tags = True
+ external_link.short_description = _('external url')
+
+ def get_form(self, request, obj=None, **kwargs):
+ """
+ Pass request to form (for ISBN magic)
+ """
+ form = super().get_form(request, obj=obj, **kwargs)
+ form.request = request
+ return form
+
+ def changeform_view(self, request, object_id=None, form_url='',
+ extra_context=None):
+ """
+ We use _continue for ISBN fetching, so remove continue button
+ """
+ extra_context = extra_context or {}
+ extra_context['show_save_and_continue'] = False
+ return super().changeform_view(request, object_id, form_url,
+ extra_context=extra_context)
+
class EmpruntAdmin(VersionAdmin):
list_display = ('media', 'user', 'date_emprunt', 'date_rendu',
diff --git a/media/forms.py b/media/forms.py
index f47b4e9..7f0b089 100644
--- a/media/forms.py
+++ b/media/forms.py
@@ -2,6 +2,9 @@
# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
+import json
+import urllib.request
+
from django.forms import ModelForm
from .models import Emprunt
@@ -11,3 +14,45 @@ class EmpruntForm(ModelForm):
class Meta:
model = Emprunt
fields = ['media']
+
+
+class MediaAdminForm(ModelForm):
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.fields['isbn'].widget.template_name = "media/isbn_button.html"
+
+ def download_data(self, isbn):
+ """
+ Download data from ISBN
+ """
+ api_url = "https://openlibrary.org/api/books?bibkeys=ISBN:{}" \
+ "&format=json&jscmd=data".format(isbn)
+ with urllib.request.urlopen(api_url) as url:
+ data = json.loads(url.read().decode())
+ if data and data['ISBN:' + isbn]:
+ data = data['ISBN:' + isbn]
+
+ # Fill the data
+ # TODO implement authors
+ if data['title']:
+ self.cleaned_data['title'] = data['title']
+ self.cleaned_data['side_title'] = data['title']
+ if data['subtitle']:
+ self.cleaned_data['subtitle'] = data['subtitle']
+ if data['url']:
+ self.cleaned_data['external_url'] = data['url']
+ if data['number_of_pages']:
+ self.cleaned_data['number_of_pages'] = \
+ data['number_of_pages']
+
+ def clean(self):
+ """
+ If user fetch ISBN data, then download data before validating the form
+ """
+ if "_continue" in self.request.POST:
+ isbn = self.cleaned_data.get('isbn')
+ if isbn:
+ # ISBN is present
+ self.download_data(isbn)
+
+ return super().clean()
diff --git a/media/locale/fr/LC_MESSAGES/django.po b/media/locale/fr/LC_MESSAGES/django.po
index 0bd4731..5b7b3ef 100644
--- a/media/locale/fr/LC_MESSAGES/django.po
+++ b/media/locale/fr/LC_MESSAGES/django.po
@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-08-10 15:55+0200\n"
+"POT-Creation-Date: 2019-08-11 10:39+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -13,46 +13,106 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-#: admin.py:47
-msgid "Turn back"
-msgstr "Rendre"
-
-#: admin.py:50
-msgid "permanencier rendu"
-msgstr ""
-
-#: models.py:17
-msgid "author"
-msgstr "auteur"
-
-#: models.py:18
+#: admin.py:31 models.py:20 models.py:51
msgid "authors"
msgstr "auteurs"
-#: models.py:30
+#: admin.py:38
+msgid "external url"
+msgstr "URL externe"
+
+#: admin.py:78
+msgid "Turn back"
+msgstr "Rendre"
+
+#: admin.py:81
+msgid "permanencier rendu"
+msgstr ""
+
+#: fields.py:17
+msgid "ISBN-10 or ISBN-13"
+msgstr "ISBN-10 ou ISBN-13"
+
+#: models.py:19
+msgid "author"
+msgstr "auteur"
+
+#: models.py:25
+msgid "ISBN"
+msgstr "ISBN"
+
+#: models.py:26
+msgid "You may be able to scan it from a bar code."
+msgstr "Peut souvent être scanné à partir du code barre."
+
+#: models.py:31
+msgid "title"
+msgstr "titre"
+
+#: models.py:35
+msgid "subtitle"
+msgstr "sous-titre"
+
+#: models.py:41
+msgid "external URL"
+msgstr "URL externe"
+
+#: models.py:46
+msgid "side title"
+msgstr "côte"
+
+#: models.py:54
+msgid "number of pages"
+msgstr "nombre de pages"
+
+#: models.py:59
+msgid "publish date"
+msgstr "date de publication"
+
+#: models.py:68
msgid "medium"
msgstr "medium"
-#: models.py:31
+#: models.py:69
msgid "media"
msgstr "media"
-#: models.py:60
+#: models.py:98
msgid "borrowed item"
msgstr "emprunt"
-#: models.py:61
+#: models.py:99
msgid "borrowed items"
msgstr "emprunts"
-#: models.py:85
+#: models.py:123
msgid "game"
msgstr "jeu"
-#: models.py:86
+#: models.py:124
msgid "games"
msgstr "jeux"
+#: templates/media/isbn_button.html:3
+msgid "Fetch data"
+msgstr "Télécharger les données"
+
+#: validators.py:20
+msgid "Invalid ISBN: Not a string"
+msgstr "ISBN invalide : ce n'est pas une chaîne de caractères"
+
+#: validators.py:23
+msgid "Invalid ISBN: Wrong length"
+msgstr "ISBN invalide : mauvaise longueur"
+
+#: validators.py:26
+msgid "Invalid ISBN: Failed checksum"
+msgstr "ISBN invalide : mauvais checksum"
+
+#: validators.py:29
+msgid "Invalid ISBN: Only upper case allowed"
+msgstr "ISBN invalide : seulement les majuscules sont autorisées"
+
#: views.py:41
msgid "Welcome to the Mediatek database"
msgstr "Bienvenue sur la base de données de la Mediatek"
diff --git a/media/static/media/isbn_fetcher.js b/media/static/media/isbn_fetcher.js
deleted file mode 100644
index 7a492e4..0000000
--- a/media/static/media/isbn_fetcher.js
+++ /dev/null
@@ -1,46 +0,0 @@
-// curl 'https://openlibrary.org/api/books?bibkeys=ISBN:0201558025&format=json&jscmd=data'
-a = {
- "ISBN:0201558025": {
- "publishers": [{"name": "Addison-Wesley"}],
- "pagination": "xiii, 657 p. :",
- "identifiers": {
- "lccn": ["93040325"],
- "openlibrary": ["OL1429049M"],
- "isbn_10": ["0201558025"],
- "wikidata": ["Q15303722"],
- "goodreads": ["112243"],
- "librarything": ["45844"]
- },
- //"subtitle": "a foundation for computer science",
- //"title": "Concrete mathematics",
- //"url": "https://openlibrary.org/books/OL1429049M/Concrete_mathematics",
- "classifications": {"dewey_decimal_class": ["510"], "lc_classifications": ["QA39.2 .G733 1994"]},
- "notes": "Includes bibliographical references (p. 604-631) and index.",
- "number_of_pages": 657,
- "cover": {
- "small": "https://covers.openlibrary.org/b/id/135182-S.jpg",
- "large": "https://covers.openlibrary.org/b/id/135182-L.jpg",
- "medium": "https://covers.openlibrary.org/b/id/135182-M.jpg"
- },
- "subjects": [{
- "url": "https://openlibrary.org/subjects/computer_science",
- "name": "Computer science"
- }, {"url": "https://openlibrary.org/subjects/mathematics", "name": "Mathematics"}],
- "publish_date": "1994",
- "key": "/books/OL1429049M",
- "authors": [{
- "url": "https://openlibrary.org/authors/OL720958A/Ronald_L._Graham",
- "name": "Ronald L. Graham"
- }, {
- "url": "https://openlibrary.org/authors/OL229501A/Donald_Knuth",
- "name": "Donald Knuth"
- }, {"url": "https://openlibrary.org/authors/OL2669938A/Oren_Patashnik", "name": "Oren Patashnik"}],
- "by_statement": "Ronald L. Graham, Donald E. Knuth, Oren Patashnik.",
- "publish_places": [{"name": "Reading, Mass"}],
- "ebooks": [{
- "formats": {},
- "preview_url": "https://archive.org/details/concretemathemat00grah_444",
- "availability": "restricted"
- }]
- }
-}
\ No newline at end of file
diff --git a/media/templates/media/isbn_button.html b/media/templates/media/isbn_button.html
new file mode 100644
index 0000000..36bd9b2
--- /dev/null
+++ b/media/templates/media/isbn_button.html
@@ -0,0 +1,3 @@
+{% load i18n %}
+{% include "django/forms/widgets/input.html" %}
+
\ No newline at end of file
diff --git a/theme/static/css/admin.css b/theme/static/css/admin.css
index f17aa66..7e43d06 100644
--- a/theme/static/css/admin.css
+++ b/theme/static/css/admin.css
@@ -121,7 +121,7 @@ input[type=button]:focus, .button:hover, input[type=submit]:hover, input[type=bu
/* Pull footer to bottom */
#content {
- min-height: calc(100vh - 190px);
+ min-height: calc(100vh - 220px);
}
.login #content {
diff --git a/users/admin.py b/users/admin.py
index 95059ea..aef5357 100644
--- a/users/admin.py
+++ b/users/admin.py
@@ -103,7 +103,6 @@ class UserAdmin(VersionAdmin, BaseUserAdmin):
'
'
)
else:
- # TODO permit adhere only if perms.users.add_user
return format_html(
'
'
'{}',