Add ISBN data downloader

This commit is contained in:
Alexandre Iooss 2019-08-11 10:40:39 +02:00
parent 2f872eccce
commit 861279d30d
No known key found for this signature in database
GPG Key ID: 6C79278F3FCDCC02
7 changed files with 158 additions and 69 deletions

View File

@ -8,6 +8,7 @@ from django.utils.translation import ugettext_lazy as _
from reversion.admin import VersionAdmin from reversion.admin import VersionAdmin
from med.admin import admin_site from med.admin import admin_site
from .forms import MediaAdminForm
from .models import Auteur, Emprunt, Jeu, Media from .models import Auteur, Emprunt, Jeu, Media
@ -17,16 +18,43 @@ class AuteurAdmin(VersionAdmin):
class MediaAdmin(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') search_fields = ('title', 'authors__nom', 'side_title', 'subtitle', 'isbn')
autocomplete_fields = ('authors',) autocomplete_fields = ('authors',)
date_hierarchy = 'publish_date' date_hierarchy = 'publish_date'
form = MediaAdminForm
def authors_list(self, obj): def authors_list(self, obj):
return ", ".join([a.nom for a in obj.authors.all()]) return ", ".join([a.nom for a in obj.authors.all()])
authors_list.short_description = _('authors') authors_list.short_description = _('authors')
def external_link(self, obj):
return format_html('<a href="{}" target="about:blank">{}</a>',
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): class EmpruntAdmin(VersionAdmin):
list_display = ('media', 'user', 'date_emprunt', 'date_rendu', list_display = ('media', 'user', 'date_emprunt', 'date_rendu',

View File

@ -2,6 +2,9 @@
# Copyright (C) 2017-2019 by BDE ENS Paris-Saclay # Copyright (C) 2017-2019 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
import json
import urllib.request
from django.forms import ModelForm from django.forms import ModelForm
from .models import Emprunt from .models import Emprunt
@ -11,3 +14,45 @@ class EmpruntForm(ModelForm):
class Meta: class Meta:
model = Emprunt model = Emprunt
fields = ['media'] 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()

View File

@ -3,7 +3,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \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" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -13,46 +13,106 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: admin.py:47 #: admin.py:31 models.py:20 models.py:51
msgid "Turn back"
msgstr "Rendre"
#: admin.py:50
msgid "permanencier rendu"
msgstr ""
#: models.py:17
msgid "author"
msgstr "auteur"
#: models.py:18
msgid "authors" msgid "authors"
msgstr "auteurs" 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" msgid "medium"
msgstr "medium" msgstr "medium"
#: models.py:31 #: models.py:69
msgid "media" msgid "media"
msgstr "media" msgstr "media"
#: models.py:60 #: models.py:98
msgid "borrowed item" msgid "borrowed item"
msgstr "emprunt" msgstr "emprunt"
#: models.py:61 #: models.py:99
msgid "borrowed items" msgid "borrowed items"
msgstr "emprunts" msgstr "emprunts"
#: models.py:85 #: models.py:123
msgid "game" msgid "game"
msgstr "jeu" msgstr "jeu"
#: models.py:86 #: models.py:124
msgid "games" msgid "games"
msgstr "jeux" 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 #: views.py:41
msgid "Welcome to the Mediatek database" msgid "Welcome to the Mediatek database"
msgstr "Bienvenue sur la base de données de la Mediatek" msgstr "Bienvenue sur la base de données de la Mediatek"

View File

@ -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"
}]
}
}

View File

@ -0,0 +1,3 @@
{% load i18n %}
{% include "django/forms/widgets/input.html" %}
<input type="submit" value="{% trans "Fetch data" %}" name="_continue">

View File

@ -121,7 +121,7 @@ input[type=button]:focus, .button:hover, input[type=submit]:hover, input[type=bu
/* Pull footer to bottom */ /* Pull footer to bottom */
#content { #content {
min-height: calc(100vh - 190px); min-height: calc(100vh - 220px);
} }
.login #content { .login #content {

View File

@ -103,7 +103,6 @@ class UserAdmin(VersionAdmin, BaseUserAdmin):
'<img src="/static/admin/img/icon-yes.svg" alt="True">' '<img src="/static/admin/img/icon-yes.svg" alt="True">'
) )
else: else:
# TODO permit adhere only if perms.users.add_user
return format_html( return format_html(
'<img src="/static/admin/img/icon-no.svg" alt="False"> ' '<img src="/static/admin/img/icon-no.svg" alt="False"> '
'<a class="button" href="{}">{}</a>', '<a class="button" href="{}">{}</a>',