From 9cd41b5a3f0121c3fa51dfda9beb912439342d24 Mon Sep 17 00:00:00 2001 From: Gabriel Augendre Date: Sat, 16 Jun 2018 09:26:10 +0200 Subject: [PATCH] Validate ISBN before sending the request to Decitre. #28 --- manuels/migrations/0026_auto_20180616_0916.py | 19 +++++++++ manuels/models.py | 3 +- manuels/static/manuels/fetch-isbn.js | 3 +- manuels/templates/manuels/add_book.html | 4 -- manuels/views.py | 40 ++++++++++++++++++- 5 files changed, 62 insertions(+), 7 deletions(-) create mode 100644 manuels/migrations/0026_auto_20180616_0916.py diff --git a/manuels/migrations/0026_auto_20180616_0916.py b/manuels/migrations/0026_auto_20180616_0916.py new file mode 100644 index 0000000..fbc46a3 --- /dev/null +++ b/manuels/migrations/0026_auto_20180616_0916.py @@ -0,0 +1,19 @@ +# Generated by Django 2.0.6 on 2018-06-16 07:16 + +from django.db import migrations, models +import manuels.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('manuels', '0025_auto_20180607_0746'), + ] + + operations = [ + migrations.AlterField( + model_name='book', + name='isbn', + field=models.CharField(help_text="Format attendu : 10 ou 13 chiffres, éventuellement séparés par des tirets et éventuellement suivis de la lettre X. La recherche sur Decitre ne fonctionnera qu'avec un code ISBN à13 chiffres (ou EAN)", max_length=20, validators=[manuels.models.isbn_validator], verbose_name='ISBN/EAN'), + ), + ] diff --git a/manuels/models.py b/manuels/models.py index cbae269..9d892b0 100644 --- a/manuels/models.py +++ b/manuels/models.py @@ -158,7 +158,8 @@ class Book(BaseModel): 'ISBN/EAN', max_length=20, help_text="Format attendu : 10 ou 13 chiffres, éventuellement séparés par des tirets et éventuellement " - "suivis de la lettre X", + "suivis de la lettre X. La recherche sur Decitre ne fonctionnera qu'avec un code ISBN à" + "13 chiffres (ou EAN)", validators=[isbn_validator] ) price = models.FloatField('prix', validators=[positive_float_validator]) diff --git a/manuels/static/manuels/fetch-isbn.js b/manuels/static/manuels/fetch-isbn.js index 140b128..0dfbdf9 100644 --- a/manuels/static/manuels/fetch-isbn.js +++ b/manuels/static/manuels/fetch-isbn.js @@ -7,13 +7,14 @@ document.addEventListener("DOMContentLoaded", function (event) { isbn.classList.add('is-invalid'); isbn.classList.remove('is-valid'); document.querySelector('#id_isbn_invalid_feedback').style.display = 'block'; - document.querySelector('#id_isbn_error_text').textContent = data.error; + document.querySelector('#id_isbn_invalid_feedback').textContent = data.error; return; } isbn.classList.remove('is-invalid'); isbn.classList.add('is-valid'); document.querySelector('#id_isbn_invalid_feedback').style.display = 'none'; + document.querySelector('#id_isbn_invalid_feedback').textContent = ''; document.querySelector('#id_title').value = data.title; document.querySelector('#id_title').classList.add('is-valid'); diff --git a/manuels/templates/manuels/add_book.html b/manuels/templates/manuels/add_book.html index 755d610..28d1f7d 100644 --- a/manuels/templates/manuels/add_book.html +++ b/manuels/templates/manuels/add_book.html @@ -53,10 +53,6 @@
- Erreur lors de la recherche. Il se peut que le livre n'existe pas dans la base de connaissance de - Decitre ou que vous ayez mal saisi l'ISBN. - Veuillez saisir les informations du livre à la main.
- Données techniques :
{{ form.isbn.help_text|safe }} diff --git a/manuels/views.py b/manuels/views.py index e9356ed..2cded29 100644 --- a/manuels/views.py +++ b/manuels/views.py @@ -227,15 +227,53 @@ class ConfirmTeacherView(BaseTeacherView, UpdateView): return response +def validate_isbn(isbn): + _sum = 0 + if len(isbn) == 10: + for i, digit in enumerate(isbn): + if digit == 'X': + digit = 10 + else: + digit = int(digit) + _sum += digit * (i + 1) + + return _sum % 11 == 0 + + elif len(isbn) == 13: + for i, digit in enumerate(isbn): + weight = 3 if i % 2 == 1 else 1 + digit = int(digit) + _sum += digit * weight + + return _sum % 10 == 0 + + return False + + @cache_page(None) def isbn_api(request, isbn): + isbn = isbn.strip().replace('-', '') + + if not validate_isbn(isbn): + return JsonResponse({ + 'error': "L'ISBN saisi n'est pas valide." + }) + + if len(isbn) == 10: + return JsonResponse({ + 'error': "La recherche sur Decitre ne fonctionne qu'avec un ISBN 13 (ou EAN)." + }) + res = requests.get(f'https://www.decitre.fr/livres/{isbn}.html') try: res.raise_for_status() except Exception as exc: + message = ("Erreur lors de la recherche. Il se peut que le livre n'existe pas dans la base de connaissances " + "de Decitre ou que vous ayez mal saisi l'ISBN. Vous pouvez toujours saisir " + "les informations du livre à la main. Message : {}").format(str(exc)) return JsonResponse({ - 'error': str(exc) + 'error': message }) decitre_soup = bs4.BeautifulSoup(res.text, "html.parser")