mirror of
				https://gitlab.crans.org/mediatek/med.git
				synced 2025-11-04 04:22:19 +01:00 
			
		
		
		
	Add ISBN data downloader
This commit is contained in:
		@@ -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('<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):
 | 
			
		||||
    list_display = ('media', 'user', 'date_emprunt', 'date_rendu',
 | 
			
		||||
 
 | 
			
		||||
@@ -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()
 | 
			
		||||
 
 | 
			
		||||
@@ -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 <EMAIL@ADDRESS>\n"
 | 
			
		||||
"Language-Team: LANGUAGE <LL@li.org>\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"
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
        }]
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								media/templates/media/isbn_button.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								media/templates/media/isbn_button.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
{% load i18n %}
 | 
			
		||||
{% include "django/forms/widgets/input.html" %}
 | 
			
		||||
<input type="submit" value="{% trans "Fetch data" %}" name="_continue">
 | 
			
		||||
@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -103,7 +103,6 @@ class UserAdmin(VersionAdmin, BaseUserAdmin):
 | 
			
		||||
                '<img src="/static/admin/img/icon-yes.svg" alt="True">'
 | 
			
		||||
            )
 | 
			
		||||
        else:
 | 
			
		||||
            # TODO permit adhere only if perms.users.add_user
 | 
			
		||||
            return format_html(
 | 
			
		||||
                '<img src="/static/admin/img/icon-no.svg" alt="False"> '
 | 
			
		||||
                '<a class="button" href="{}">{}</a>',
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user