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): 'True' ) else: - # TODO permit adhere only if perms.users.add_user return format_html( 'False ' '{}',