1
0
mirror of https://gitlab.crans.org/mediatek/med.git synced 2024-11-26 21:27:11 +00:00

Add page to search a media by its ISBN

This commit is contained in:
Yohann D'ANELLO 2020-09-25 10:27:43 +02:00
parent d1e9693647
commit 796c985ffb
23 changed files with 232 additions and 30 deletions

View File

@ -3,7 +3,6 @@
from django.test import TestCase from django.test import TestCase
from django.urls import reverse from django.urls import reverse
from users.models import User from users.models import User
""" """

View File

@ -9,7 +9,6 @@ from django.db.models import Count
from django.shortcuts import render from django.shortcuts import render
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from reversion.models import Revision from reversion.models import Revision
from med.settings import PAGINATION_NUMBER from med.settings import PAGINATION_NUMBER
from users.models import User from users.models import User

View File

@ -45,6 +45,7 @@ INSTALLED_APPS = [
'django.contrib.sites', 'django.contrib.sites',
'django.contrib.messages', 'django.contrib.messages',
'django.contrib.staticfiles', 'django.contrib.staticfiles',
'django_filters',
# Med apps # Med apps
'users', 'users',

View File

@ -2,10 +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
from django.contrib.auth.decorators import login_required
from django.contrib.auth.views import PasswordResetView from django.contrib.auth.views import PasswordResetView
from django.urls import include, path from django.urls import include, path
from django.views.generic import RedirectView, TemplateView from django.views.generic import RedirectView
from rest_framework import routers from rest_framework import routers
import media.views import media.views
@ -15,7 +14,13 @@ from .admin import admin_site
# API router # API router
router = routers.DefaultRouter() router = routers.DefaultRouter()
router.register(r'authors', media.views.AuteurViewSet) router.register(r'authors', media.views.AuteurViewSet)
router.register(r'media', media.views.MediaViewSet) router.register(r'media/bd', media.views.BDViewSet)
router.register(r'media/manga', media.views.MangaViewSet)
router.register(r'media/cd', media.views.CDViewSet)
router.register(r'media/vinyle', media.views.VinyleViewSet)
router.register(r'media/roman', media.views.RomanViewSet)
router.register(r'media/revue', media.views.RevueViewSet)
router.register(r'media/future', media.views.FutureMediaViewSet)
router.register(r'borrowed_items', media.views.EmpruntViewSet) router.register(r'borrowed_items', media.views.EmpruntViewSet)
router.register(r'games', media.views.JeuViewSet) router.register(r'games', media.views.JeuViewSet)
router.register(r'users', users.views.UserViewSet) router.register(r'users', users.views.UserViewSet)

View File

@ -6,8 +6,8 @@ from django.urls import reverse
from django.utils.html import format_html from django.utils.html import format_html
from django.utils.translation import ugettext_lazy as _ 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 .forms import MediaAdminForm
from .models import Auteur, BD, CD, Emprunt, FutureMedia, Jeu, Manga,\ from .models import Auteur, BD, CD, Emprunt, FutureMedia, Jeu, Manga,\
Revue, Roman, Vinyle Revue, Roman, Vinyle

View File

@ -2,7 +2,6 @@ from argparse import FileType
from sys import stdin from sys import stdin
from django.core.management import BaseCommand from django.core.management import BaseCommand
from media.models import Auteur, CD from media.models import Auteur, CD

View File

@ -2,7 +2,6 @@ from time import sleep
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.management import BaseCommand from django.core.management import BaseCommand
from media.forms import MediaAdminForm from media.forms import MediaAdminForm
from media.models import BD, FutureMedia, Manga, Roman from media.models import BD, FutureMedia, Manga, Roman

View File

@ -3,7 +3,6 @@ from sys import stdin
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.management import BaseCommand from django.core.management import BaseCommand
from media.models import BD, FutureMedia, Manga, Roman from media.models import BD, FutureMedia, Manga, Roman
from media.validators import isbn_validator from media.validators import isbn_validator

View File

@ -4,7 +4,6 @@ from argparse import FileType
from sys import stdin from sys import stdin
from django.core.management import BaseCommand from django.core.management import BaseCommand
from media.models import Auteur, Roman from media.models import Auteur, Roman

View File

@ -2,7 +2,6 @@ from argparse import FileType
from sys import stdin from sys import stdin
from django.core.management import BaseCommand from django.core.management import BaseCommand
from media.models import Auteur, Vinyle from media.models import Auteur, Vinyle

View File

@ -1,7 +1,6 @@
from time import sleep from time import sleep
from django.core.management import BaseCommand from django.core.management import BaseCommand
from media.forms import MediaAdminForm from media.forms import MediaAdminForm
from media.models import BD, Manga from media.models import BD, Manga

View File

@ -4,7 +4,6 @@
import re import re
import requests import requests
from media.models import Auteur from media.models import Auteur

View File

@ -1,20 +1,54 @@
from rest_framework import serializers from rest_framework import serializers
from .models import Auteur, BD, Emprunt, Jeu from .models import Auteur, BD, CD, FutureMedia, Manga, Emprunt, Jeu, Revue, Roman, Vinyle
class AuteurSerializer(serializers.HyperlinkedModelSerializer): class AuteurSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Auteur model = Auteur
fields = ['url', 'name'] fields = ['url', 'name']
class MediaSerializer(serializers.HyperlinkedModelSerializer): class BDSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = BD model = BD
fields = ['url', 'isbn', 'title', 'subtitle', 'external_url', fields = '__all__'
'side_identifier', 'authors', 'number_of_pages',
'publish_date']
class MangaSerializer(serializers.ModelSerializer):
class Meta:
model = Manga
fields = '__all__'
class CDSerializer(serializers.ModelSerializer):
class Meta:
model = CD
fields = '__all__'
class VinyleSerializer(serializers.ModelSerializer):
class Meta:
model = Vinyle
fields = '__all__'
class RomanSerializer(serializers.ModelSerializer):
class Meta:
model = Roman
fields = '__all__'
class RevueSerializer(serializers.ModelSerializer):
class Meta:
model = Revue
fields = '__all__'
class FutureMediaSerializer(serializers.ModelSerializer):
class Meta:
model = FutureMedia
fields = '__all__'
class EmpruntSerializer(serializers.HyperlinkedModelSerializer): class EmpruntSerializer(serializers.HyperlinkedModelSerializer):

View File

@ -0,0 +1,92 @@
{% extends "base.html" %}
{% block content %}
<form action="#" onsubmit="searchISBN()">
<label for="isbn" id="id_isbn_label">ISBN :</label>
<input type="text" id="isbn" autofocus />
<input type="submit" id="isbn_search" />
</form>
<ul id="result"></ul>
{% endblock %}
{% block extrajavascript %}
<script>
function searchISBN() {
let isbn = document.getElementById("isbn").value;
let result_div = document.getElementById("result");
result_div.innerHTML = "<li id='recap-isbn'>Recherche : " + isbn + "</li>";
document.getElementById("isbn").value = "";
document.getElementById("isbn").focus();
let bd_request = new XMLHttpRequest();
bd_request.open('GET', '/api/media/bd/?search=' + isbn, true);
bd_request.onload = function () {
let data = JSON.parse(this.response);
data.results.forEach(bd => {
result_div.innerHTML += "<li id='bd_" + bd.id + "'>" +
"<a href='/database/media/bd/" + bd.id + "/change/'>BD : "
+ bd.title + (bd.subtitle ? " - " + bd.subtitle : "") + "</a></li>";
});
}
bd_request.send();
let manga_request = new XMLHttpRequest();
manga_request.open('GET', '/api/media/manga/?search=' + isbn, true);
manga_request.onload = function () {
let data = JSON.parse(this.response);
data.results.forEach(manga => {
result_div.innerHTML += "<li id='manga_" + manga.id + "'>" +
"<a href='/database/media/manga/" + manga.id + "/change/'>Manga : "
+ manga.title + (manga.subtitle ? " - " + manga.subtitle : "") + "</a></li>";
});
}
manga_request.send();
let cd_request = new XMLHttpRequest();
cd_request.open('GET', '/api/media/cd/?search=' + isbn, true);
cd_request.onload = function () {
let data = JSON.parse(this.response);
data.results.forEach(cd => {
result_div.innerHTML += "<li id='cd_" + cd.id + "'>" +
"<a href='/database/media/cd/" + cd.id + "/change/'>CD : " + cd.title + "</a></li>";
});
}
cd_request.send();
let vinyle_request = new XMLHttpRequest();
vinyle_request.open('GET', '/api/media/vinyle/?search=' + isbn, true);
vinyle_request.onload = function () {
let data = JSON.parse(this.response);
data.results.forEach(vinyle => {
result_div.innerHTML += "<li id='vinyle_" + vinyle.id + "'>" +
"<a href='/database/media/vinyle/" + vinyle.id + "/change/'>Vinyle : " + vinyle.title + "</a></li>";
});
}
vinyle_request.send();
let roman_request = new XMLHttpRequest();
roman_request.open('GET', '/api/media/roman/?search=' + isbn, true);
roman_request.onload = function () {
let data = JSON.parse(this.response);
data.results.forEach(roman => {
result_div.innerHTML += "<li id='roman_" + roman.id + "'>" +
"<a href='/database/media/roman/" + roman.id + "/change/'>Roman : " + roman.title + "</a></li>";
});
}
roman_request.send();
let future_request = new XMLHttpRequest();
future_request.open('GET', '/api/media/future/?search=' + isbn, true);
future_request.onload = function () {
let data = JSON.parse(this.response);
data.results.forEach(future => {
result_div.innerHTML += "<li id='future_" + future.id + "'>" +
"<a href='/database/media/future/" + future.id + "/change/'>Medium non traité : "
+ future.title + "</a></li>";
});
}
future_request.send();
}
</script>
{% endblock %}

View File

@ -3,7 +3,6 @@
from django.test import TestCase from django.test import TestCase
from django.urls import reverse from django.urls import reverse
from media.models import Auteur, BD from media.models import Auteur, BD
from users.models import User from users.models import User

View File

@ -3,6 +3,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.conf.urls import url from django.conf.urls import url
from django.urls import path
from . import views from . import views
@ -10,4 +11,5 @@ app_name = 'media'
urlpatterns = [ urlpatterns = [
url(r'^retour_emprunt/(?P<empruntid>[0-9]+)$', views.retour_emprunt, url(r'^retour_emprunt/(?P<empruntid>[0-9]+)$', views.retour_emprunt,
name='retour-emprunt'), name='retour-emprunt'),
path('find/', views.FindMediumView.as_view()),
] ]

View File

@ -4,16 +4,20 @@
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.decorators import login_required, permission_required from django.contrib.auth.decorators import login_required, permission_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django_filters.rest_framework import DjangoFilterBackend
from django.db import transaction from django.db import transaction
from django.shortcuts import redirect, render from django.shortcuts import redirect, render
from django.utils import timezone from django.utils import timezone
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.views.generic import TemplateView
from rest_framework import viewsets from rest_framework import viewsets
from rest_framework.filters import SearchFilter
from reversion import revisions as reversion from reversion import revisions as reversion
from .models import Auteur, BD, Emprunt, Jeu from .models import Auteur, BD, CD, Emprunt, FutureMedia, Jeu, Manga, Revue, Roman, Vinyle
from .serializers import AuteurSerializer, EmpruntSerializer, \ from .serializers import AuteurSerializer, BDSerializer, CDSerializer, EmpruntSerializer, FutureMediaSerializer, \
JeuSerializer, MediaSerializer JeuSerializer, MangaSerializer, RevueSerializer, RomanSerializer, VinyleSerializer
@login_required @login_required
@ -45,6 +49,10 @@ def index(request):
}) })
class FindMediumView(LoginRequiredMixin, TemplateView):
template_name = "media/find_medium.html"
class AuteurViewSet(viewsets.ModelViewSet): class AuteurViewSet(viewsets.ModelViewSet):
""" """
API endpoint that allows authors to be viewed or edited. API endpoint that allows authors to be viewed or edited.
@ -53,12 +61,82 @@ class AuteurViewSet(viewsets.ModelViewSet):
serializer_class = AuteurSerializer serializer_class = AuteurSerializer
class MediaViewSet(viewsets.ModelViewSet): class BDViewSet(viewsets.ModelViewSet):
""" """
API endpoint that allows media to be viewed or edited. API endpoint that allows media to be viewed or edited.
""" """
queryset = BD.objects.all() queryset = BD.objects.all()
serializer_class = MediaSerializer serializer_class = BDSerializer
filter_backends = [DjangoFilterBackend, SearchFilter]
filterset_fields = ["isbn", "side_identifier"]
search_fields = ["isbn", "$title", "$subtitle", "side_identifier", "$authors__name"]
class MangaViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows media to be viewed or edited.
"""
queryset = Manga.objects.all()
serializer_class = MangaSerializer
filter_backends = [DjangoFilterBackend, SearchFilter]
filterset_fields = ["isbn", "side_identifier"]
search_fields = ["isbn", "$title", "$subtitle", "side_identifier", "$authors__name"]
class CDViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows media to be viewed or edited.
"""
queryset = CD.objects.all()
serializer_class = CDSerializer
filter_backends = [DjangoFilterBackend, SearchFilter]
filterset_fields = ["side_identifier"]
search_fields = ["$title", "side_identifier", "$authors__name"]
class VinyleViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows media to be viewed or edited.
"""
queryset = Vinyle.objects.all()
serializer_class = VinyleSerializer
filter_backends = [DjangoFilterBackend, SearchFilter]
filterset_fields = ["side_identifier", "rpm"]
search_fields = ["$title", "side_identifier", "$authors__name"]
class RomanViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows media to be viewed or edited.
"""
queryset = Roman.objects.all()
serializer_class = RomanSerializer
filter_backends = [DjangoFilterBackend, SearchFilter]
filterset_fields = ["isbn", "side_identifier", "number_of_pages"]
search_fields = ["$title", "$subtitle", "side_identifier", "$authors__name"]
class RevueViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows media to be viewed or edited.
"""
queryset = Revue.objects.all()
serializer_class = RevueSerializer
filter_backends = [DjangoFilterBackend, SearchFilter]
filterset_fields = ["number", "year", "month", "day", "double"]
search_fields = ["$title"]
class FutureMediaViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows media to be viewed or edited.
"""
queryset = FutureMedia.objects.all()
serializer_class = FutureMediaSerializer
filter_backends = [DjangoFilterBackend, SearchFilter]
filterset_fields = ["isbn"]
search_fields = ["$isbn"]
class EmpruntViewSet(viewsets.ModelViewSet): class EmpruntViewSet(viewsets.ModelViewSet):

View File

@ -4,7 +4,7 @@ Pillow~=5.4.1
pytz~=2019.1 pytz~=2019.1
six~=1.12.0 six~=1.12.0
sqlparse~=0.2.4 sqlparse~=0.2.4
django-cas-client~=1.2.0 django-filter~=2.1.0
django-reversion~=3.0.3 django-reversion~=3.0.3
python-stdnum~=1.10 python-stdnum~=1.10
djangorestframework~=3.9.0 djangorestframework~=3.9.0

View File

@ -115,4 +115,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
}); });
} }
</script> </script>
{% block extrajavascript %}{% endblock %}
{% endblock %} {% endblock %}

View File

@ -10,8 +10,8 @@ from django.urls import reverse
from django.utils.html import format_html from django.utils.html import format_html
from django.utils.translation import ugettext_lazy as _ 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 UserCreationAdminForm from .forms import UserCreationAdminForm
from .models import Adhesion, User from .models import Adhesion, User

View File

@ -6,7 +6,6 @@ from django.contrib.auth.models import AbstractUser
from django.db import models from django.db import models
from django.utils import timezone from django.utils import timezone
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from med.settings import MAX_EMPRUNT from med.settings import MAX_EMPRUNT

View File

@ -4,7 +4,6 @@
from django.core import mail from django.core import mail
from django.test import TestCase from django.test import TestCase
from django.urls import reverse from django.urls import reverse
from users.models import User from users.models import User
""" """

View File

@ -11,9 +11,9 @@ from django.template.context_processors import csrf
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from rest_framework import viewsets from rest_framework import viewsets
from reversion import revisions as reversion from reversion import revisions as reversion
from users.forms import BaseInfoForm from users.forms import BaseInfoForm
from users.models import Adhesion, User from users.models import Adhesion, User
from .serializers import GroupSerializer, UserSerializer from .serializers import GroupSerializer, UserSerializer