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

Merge branch 'small-cleanup' into 'main'

Small cleanup

See merge request mediatek/med!4
This commit is contained in:
ynerant 2021-10-23 19:09:04 +02:00
commit 1ab06af5c7
31 changed files with 330 additions and 307 deletions

View File

@ -2,30 +2,6 @@ stages:
- test
- quality-assurance
py37-django22:
stage: test
image: debian:buster-backports
before_script:
- >
apt-get update &&
apt-get install --no-install-recommends -t buster-backports -y
python3-django python3-django-casclient python3-django-reversion python3-djangorestframework
python3-docutils python3-pil python3-tz python3-six python3-sqlparse python3-stdnum python3-yaml python3-coreapi tox
script: tox -e py37
py38-django22:
stage: test
image: ubuntu:20.04
before_script:
# Fix tzdata prompt
- ln -sf /usr/share/zoneinfo/Europe/Paris /etc/localtime && echo Europe/Paris > /etc/timezone
- >
apt-get update &&
apt-get install --no-install-recommends -y
python3-django python3-django-casclient python3-django-reversion python3-djangorestframework
python3-docutils python3-pil python3-tz python3-six python3-sqlparse python3-stdnum python3-yaml python3-coreapi tox
script: tox -e py38
py39-django22:
stage: test
image: debian:bullseye
@ -33,13 +9,13 @@ py39-django22:
- >
apt-get update &&
apt-get install --no-install-recommends -y
python3-django python3-django-casclient python3-django-reversion python3-djangorestframework
python3-docutils python3-pil python3-tz python3-six python3-sqlparse python3-stdnum python3-yaml python3-coreapi tox
python3-django python3-django-reversion python3-djangorestframework
python3-docutils python3-requests tox
script: tox -e py39
linters:
stage: quality-assurance
image: debian:buster-backports
image: debian:bullseye
before_script:
- apt-get update && apt-get install -y tox
script: tox -e linters

View File

@ -90,10 +90,6 @@ bureau
media | Can add borrowed item
media | Can change borrowed item
media | Can delete borrowed item
users | Can view adhesion
users | Can add adhesion
users | Can change adhesion
users | Can delete adhesion
users | Can view user
users | Can add user
users | Can change user

View File

@ -35,6 +35,7 @@ INSTALLED_APPS = [
# External apps
'reversion',
'rest_framework',
'django_extensions',
# Django contrib
'django.contrib.admin',

View File

@ -13,21 +13,21 @@ from .admin import admin_site
# API router
router = routers.DefaultRouter()
router.register(r'authors', media.views.AuteurViewSet)
router.register(r'media/bd', media.views.BDViewSet)
router.register(r'authors', media.views.AuthorViewSet)
router.register(r'media/comic', media.views.ComicViewSet)
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'media/vinyl', media.views.VinylViewSet)
router.register(r'media/novel', media.views.NovelViewSet)
router.register(r'media/review', media.views.ReviewViewSet)
router.register(r'media/future', media.views.FutureMediumViewSet)
router.register(r'borrowed_items', media.views.EmpruntViewSet)
router.register(r'games', media.views.JeuViewSet)
router.register(r'games', media.views.GameViewSet)
router.register(r'users', users.views.UserViewSet)
router.register(r'groups', users.views.GroupViewSet)
urlpatterns = [
path('', media.views.index, name='index'),
path('', media.views.IndexView, name='index'),
# Include project routers
path('users/', include('users.urls')),

View File

@ -9,16 +9,16 @@ from med.admin import admin_site
from reversion.admin import VersionAdmin
from .forms import MediaAdminForm
from .models import Auteur, BD, CD, Emprunt, FutureMedia, Jeu, Manga,\
Revue, Roman, Vinyle
from .models import Author, CD, Comic, Emprunt, FutureMedium, Game, Manga,\
Novel, Review, Vinyl
class AuteurAdmin(VersionAdmin):
class AuthorAdmin(VersionAdmin):
list_display = ('name',)
search_fields = ('name',)
class MediaAdmin(VersionAdmin):
class MediumAdmin(VersionAdmin):
list_display = ('__str__', 'authors_list', 'side_identifier', 'isbn',
'external_link')
search_fields = ('title', 'authors__name', 'side_identifier', 'subtitle',
@ -61,7 +61,7 @@ class MediaAdmin(VersionAdmin):
extra_context=extra_context)
class FutureMediaAdmin(VersionAdmin):
class FutureMediumAdmin(VersionAdmin):
list_display = ('isbn',)
search_fields = ('isbn',)
@ -88,7 +88,7 @@ class CDAdmin(VersionAdmin):
authors_list.short_description = _('authors')
class VinyleAdmin(VersionAdmin):
class VinylAdmin(VersionAdmin):
list_display = ('title', 'authors_list', 'side_identifier', 'rpm',)
search_fields = ('title', 'authors__name', 'side_identifier', 'rpm',)
autocomplete_fields = ('authors',)
@ -99,7 +99,7 @@ class VinyleAdmin(VersionAdmin):
authors_list.short_description = _('authors')
class RevueAdmin(VersionAdmin):
class ReviewAdmin(VersionAdmin):
list_display = ('__str__', 'number', 'year', 'month', 'day', 'double',)
search_fields = ('title', 'number', 'year',)
@ -140,20 +140,20 @@ class EmpruntAdmin(VersionAdmin):
return super().add_view(request, form_url, extra_context)
class JeuAdmin(VersionAdmin):
list_display = ('name', 'proprietaire', 'duree', 'nombre_joueurs_min',
'nombre_joueurs_max', 'comment')
search_fields = ('name', 'proprietaire__username', 'duree', 'comment')
autocomplete_fields = ('proprietaire',)
class GameAdmin(VersionAdmin):
list_display = ('name', 'owner', 'duration', 'players_min',
'players_max', 'comment')
search_fields = ('name', 'owner__username', 'duration', 'comment')
autocomplete_fields = ('owner',)
admin_site.register(Auteur, AuteurAdmin)
admin_site.register(BD, MediaAdmin)
admin_site.register(Manga, MediaAdmin)
admin_site.register(Roman, MediaAdmin)
admin_site.register(Author, AuthorAdmin)
admin_site.register(Comic, MediumAdmin)
admin_site.register(Manga, MediumAdmin)
admin_site.register(Novel, MediumAdmin)
admin_site.register(CD, CDAdmin)
admin_site.register(Vinyle, VinyleAdmin)
admin_site.register(Revue, RevueAdmin)
admin_site.register(FutureMedia, FutureMediaAdmin)
admin_site.register(Vinyl, VinylAdmin)
admin_site.register(Review, ReviewAdmin)
admin_site.register(FutureMedium, FutureMediumAdmin)
admin_site.register(Emprunt, EmpruntAdmin)
admin_site.register(Jeu, JeuAdmin)
admin_site.register(Game, GameAdmin)

View File

@ -13,7 +13,7 @@ from django.db.models import QuerySet
from django.forms import ModelForm
from django.utils.translation import gettext_lazy as _
from .models import Auteur, BD
from .models import Author, Comic
from .scraper import BedetequeScraper
@ -123,7 +123,7 @@ class MediaAdminForm(ModelForm):
self.cleaned_data["publish_date"] += "-01"
self.cleaned_data["number_of_pages"] = data["pages"]
self.cleaned_data["authors"] = \
list(Auteur.objects.get_or_create(name=author_name)[0]
list(Author.objects.get_or_create(name=author_name)[0]
for author_name in data["authors"])
self.cleaned_data["external_url"] = data["image"]
return True
@ -138,7 +138,7 @@ class MediaAdminForm(ModelForm):
if not r:
return False
# If results, then take the most accurate
data = scraper.scrap_bd_info(r[0])
data = scraper.scrap_comic_info(r[0])
self.cleaned_data.update(data)
return True
@ -195,7 +195,7 @@ class MediaAdminForm(ModelForm):
if 'authors' in info:
for author in info['authors']:
author_obj = Auteur.objects.get_or_create(
author_obj = Author.objects.get_or_create(
name=author)[0]
self.cleaned_data['authors'].append(author_obj)
@ -269,7 +269,7 @@ class MediaAdminForm(ModelForm):
if 'authors' in data:
for author in data['authors']:
author_obj = Auteur.objects.get_or_create(
author_obj = Author.objects.get_or_create(
name=author['name'])[0]
self.cleaned_data['authors'].append(author_obj)
@ -343,7 +343,7 @@ class MediaAdminForm(ModelForm):
self.add_error(name, e)
class Meta:
model = BD
model = Comic
fields = ('isbn', 'title', 'subtitle', 'external_url',
'side_identifier', 'authors', 'number_of_pages',
'publish_date', 'present', )

View File

@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-10-02 13:02+0200\n"
"POT-Creation-Date: 2021-10-23 18:27+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,20 +13,20 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: admin.py:34 admin.py:89 admin.py:100 models.py:29 models.py:65 models.py:130
#: admin.py:33 admin.py:88 admin.py:99 models.py:29 models.py:65 models.py:130
#: models.py:192 models.py:243 models.py:274
msgid "authors"
msgstr "auteurs"
#: admin.py:44
#: admin.py:43
msgid "external url"
msgstr "URL externe"
#: admin.py:127
#: admin.py:126
msgid "Turn back"
msgstr "Rendre"
#: admin.py:130 models.py:407
#: admin.py:129 models.py:407
msgid "given back to"
msgstr "rendu à"
@ -34,7 +34,7 @@ msgstr "rendu à"
msgid "ISBN-10 or ISBN-13"
msgstr "ISBN-10 ou ISBN-13"
#: forms.py:244
#: forms.py:301
msgid "This ISBN is not found."
msgstr "L'ISBN n'a pas été trouvé."
@ -94,11 +94,11 @@ msgid "Tell that the medium is present in the Mediatek."
msgstr "Indique que le medium est présent à la Mediatek."
#: models.py:93 models.py:355
msgid "BD"
msgid "comic"
msgstr "BD"
#: models.py:94
msgid "BDs"
msgid "comics"
msgstr "BDs"
#: models.py:155
@ -110,11 +110,11 @@ msgid "mangas"
msgstr "mangas"
#: models.py:217
msgid "roman"
msgid "novel"
msgstr "roman"
#: models.py:218
msgid "romans"
msgid "novels"
msgstr "romans"
#: models.py:234
@ -130,12 +130,12 @@ msgid "45 RPM"
msgstr "45 TPM"
#: models.py:256
msgid "vinyle"
msgid "vinyl"
msgstr "vinyle"
#: models.py:257
msgid "vinyles"
msgstr "vinyle"
msgid "vinyls"
msgstr "vinyles"
#: models.py:287
msgid "CD"
@ -166,11 +166,11 @@ msgid "double"
msgstr "double"
#: models.py:338
msgid "revue"
msgid "review"
msgstr "revue"
#: models.py:339
msgid "revues"
msgid "reviews"
msgstr "revues"
#: models.py:353
@ -277,12 +277,6 @@ msgstr "ISBN invalide : mauvaise longueur"
msgid "Invalid ISBN: Only upper case allowed"
msgstr "ISBN invalide : seulement les majuscules sont autorisées"
#: views.py:50
#: views.py:51
msgid "Welcome to the Mediatek database"
msgstr "Bienvenue sur la base de données de la Mediatek"
#~ msgid "medium"
#~ msgstr "medium"
#~ msgid "media"
#~ msgstr "media"

View File

@ -1,5 +1,5 @@
from django.core.management import BaseCommand
from media.models import BD, CD, Manga, Revue, Roman, Vinyle, Jeu
from media.models import Comic, CD, Manga, Review, Novel, Vinyl, Game
class Command(BaseCommand):
@ -18,9 +18,9 @@ class Command(BaseCommand):
f.write("Ce site répertorie l'intégralité des media présents "
"à la Mediatek de l'ENS Paris-Saclay.\n")
for model_class, file_name in [(BD, "bd.md"), (Manga, "mangas.md"),
(Roman, "romans.md"),
(CD, "cd.md"), (Vinyle, "vinyles.md")]:
for model_class, file_name in [(Comic, "bd.md"), (Manga, "mangas.md"),
(Novel, "romans.md"),
(CD, "cd.md"), (Vinyl, "vinyles.md")]:
self.process_model_class(model_class, file_name, f, directory)
# Traitement différent pour les revues
@ -28,13 +28,13 @@ class Command(BaseCommand):
f.write("# Revues\n\n\n")
titles = list(set(obj["title"] for obj in
Revue.objects.values("title").distinct().all()))
Review.objects.values("title").distinct().all()))
titles.sort()
for title in titles:
f.write(f"## {title}\n\n\n")
for medium in Revue.objects.filter(title=title)\
for medium in Review.objects.filter(title=title)\
.order_by("number").all():
f.write(f"### Numéro {medium.number}\n\n\n")
if medium.double:
@ -51,13 +51,13 @@ class Command(BaseCommand):
with open(directory + "/docs/jeux.md", "w") as f:
f.write("# Jeux\n\n\n")
for game in Jeu.objects.order_by("name").all():
for game in Game.objects.order_by("name").all():
f.write(f"## {game.name}\n\n\n")
f.write(f"Durée : {game.duree}\n\n")
f.write(f"Nombre de joueurs : {game.nombre_joueurs_min} "
f"- {game.nombre_joueurs_max}\n\n")
if game.proprietaire.username != "Med":
f.write(f"Propriétaire : {game.proprietaire.username}\n\n")
f.write(f"Durée : {game.duration}\n\n")
f.write(f"Nombre de joueurs : {game.players_min} "
f"- {game.players_max}\n\n")
if game.owner.username != "Med":
f.write(f"Propriétaire : {game.owner.username}\n\n")
if game.comment:
f.write(f"Commentaire : {game.comment}\n\n")
f.write("\n\n\n")

View File

@ -2,7 +2,7 @@ from argparse import FileType
from sys import stdin
from django.core.management import BaseCommand
from media.models import Auteur, CD
from media.models import Author, CD
class Command(BaseCommand):
@ -29,7 +29,7 @@ class Command(BaseCommand):
title = cd[0]
side = cd[1]
authors_str = cd[2].split('|')
authors = [Auteur.objects.get_or_create(name=author)[0]
authors = [Author.objects.get_or_create(name=author)[0]
for author in authors_str]
cd, created = CD.objects.get_or_create(
title=title,

View File

@ -3,20 +3,20 @@ from time import sleep
from django.core.management import BaseCommand
from media.forms import MediaAdminForm
from media.models import BD, FutureMedia, Manga, Roman
from media.models import Comic, FutureMedium, Manga, Novel
class Command(BaseCommand):
def handle(self, *args, **options):
for future_medium in FutureMedia.objects.all():
for future_medium in FutureMedium.objects.all():
isbn = future_medium.isbn
type_str = future_medium.type
if type_str == 'bd':
cl = BD
cl = Comic
elif type_str == 'manga':
cl = Manga
elif type_str == 'roman':
cl = Roman
cl = Novel
else:
self.stderr.write(self.style.WARNING(
"Unknown medium type: {type}. Ignoring..."

View File

@ -3,7 +3,7 @@ from sys import stdin
from django.core.exceptions import ValidationError
from django.core.management import BaseCommand
from media.models import BD, FutureMedia, Manga, Roman
from media.models import Comic, FutureMedium, Manga, Novel
from media.validators import isbn_validator
@ -27,7 +27,7 @@ class Command(BaseCommand):
def handle(self, *args, **options):
type_str = options["media_type"]
media_classes = [BD, Manga, Roman, FutureMedia]
media_classes = [Comic, Manga, Novel, FutureMedium]
file = options["input"]
isbns = []
@ -70,7 +70,7 @@ class Command(BaseCommand):
if isbn_exists:
continue
FutureMedia.objects.create(isbn=isbn, type=type_str)
FutureMedium.objects.create(isbn=isbn, type=type_str)
self.stdout.write(self.style.SUCCESS("ISBN {isbn} imported"
.format(isbn=isbn)))
imported += 1

View File

@ -2,7 +2,7 @@ from argparse import FileType
from sys import stdin
from django.core.management import BaseCommand
from media.models import Auteur, BD
from media.models import Author, Comic
class Command(BaseCommand):
@ -28,9 +28,9 @@ class Command(BaseCommand):
title = revue[0]
number = revue[1]
authors = [Auteur.objects.get_or_create(name=n)[0]
authors = [Author.objects.get_or_create(name=n)[0]
for n in revue[2].split('|')]
bd = BD.objects.create(
bd = Comic.objects.create(
title=title,
subtitle=number,
side_identifier="{:.3} {:.3} {:0>2}"

View File

@ -3,7 +3,7 @@ from sys import stdin
from django.core.management import BaseCommand
from media.forms import generate_side_identifier
from media.models import Roman, Auteur
from media.models import Novel, Author
class Command(BaseCommand):
@ -28,10 +28,10 @@ class Command(BaseCommand):
continue
title = book[1]
authors = [Auteur.objects.get_or_create(name=n)[0]
authors = [Author.objects.get_or_create(name=n)[0]
for n in book[0].split(';')]
side_identifier = generate_side_identifier(title, authors)
roman = Roman.objects.create(
roman = Novel.objects.create(
title=title,
side_identifier=side_identifier,
)

View File

@ -2,7 +2,7 @@ from argparse import FileType
from sys import stdin
from django.core.management import BaseCommand
from media.models import Revue
from media.models import Review
class Command(BaseCommand):
@ -37,7 +37,7 @@ class Command(BaseCommand):
year = revue[4]
if not year:
year = None
revue, created = Revue.objects.get_or_create(
revue, created = Review.objects.get_or_create(
title=title,
number=number.replace('*', ''),
year=year,

View File

@ -2,7 +2,7 @@ from argparse import FileType
from sys import stdin
from django.core.management import BaseCommand
from media.models import Auteur, Vinyle
from media.models import Author, Vinyl
class Command(BaseCommand):
@ -36,9 +36,9 @@ class Command(BaseCommand):
title = vinyle[1 if rpm == 33 else 2]
authors_str = vinyle[2 if rpm == 33 else 1]\
.split('|' if rpm == 33 else ';')
authors = [Auteur.objects.get_or_create(name=author)[0]
authors = [Author.objects.get_or_create(name=author)[0]
for author in authors_str]
vinyle, created = Vinyle.objects.get_or_create(
vinyle, created = Vinyl.objects.get_or_create(
title=title,
side_identifier=side,
rpm=rpm,

View File

@ -1,7 +1,7 @@
from django.core.management import BaseCommand
from django.db import transaction
from media.forms import generate_side_identifier
from media.models import BD, Manga, Roman
from media.models import Comic, Manga, Novel
class Command(BaseCommand):
@ -24,11 +24,11 @@ class Command(BaseCommand):
t = options["type"]
medium_class = None
if t == "bd":
medium_class = BD
medium_class = Comic
elif t == "manga":
medium_class = Manga
elif t == "roman":
medium_class = Roman
medium_class = Novel
interactive_mode = not options["noninteractivemode"]

View File

@ -2,7 +2,7 @@ from time import sleep
from django.core.management import BaseCommand
from media.forms import MediaAdminForm
from media.models import BD, Manga
from media.models import Comic, Manga
class Command(BaseCommand):
@ -14,7 +14,7 @@ class Command(BaseCommand):
def handle(self, *args, **options):
converted = 0
for media in BD.objects.all():
for media in Comic.objects.all():
if media.pk < 3400:
continue
# We sleep 5 seconds to avoid a ban from Bedetheque

View File

@ -0,0 +1,61 @@
# Generated by Django 2.2.17 on 2021-10-23 16:30
from django.conf import settings
from django.db import migrations, models
import media.fields
import media.validators
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('media', '0039_mark_media_present'),
]
operations = [
migrations.RenameModel(
old_name='Auteur',
new_name='Author',
),
migrations.RenameModel(
old_name='Roman',
new_name='Comic',
),
migrations.RenameModel(
old_name='Jeu',
new_name='Game',
),
migrations.RenameModel(
old_name='BD',
new_name='Novel',
),
migrations.RenameModel(
old_name='Revue',
new_name='Review',
),
migrations.RenameModel(
old_name='Vinyle',
new_name='Vinyl',
),
migrations.RenameModel(
old_name='FutureMedia',
new_name='FutureMedium',
),
migrations.AlterModelOptions(
name='comic',
options={'ordering': ['title', 'subtitle'], 'verbose_name': 'comic', 'verbose_name_plural': 'comics'},
),
migrations.AlterModelOptions(
name='novel',
options={'ordering': ['title', 'subtitle'], 'verbose_name': 'novel', 'verbose_name_plural': 'novels'},
),
migrations.AlterModelOptions(
name='review',
options={'ordering': ['title', 'number'], 'verbose_name': 'review', 'verbose_name_plural': 'reviews'},
),
migrations.AlterModelOptions(
name='vinyl',
options={'ordering': ['title'], 'verbose_name': 'vinyl', 'verbose_name_plural': 'vinyls'},
),
]

View File

@ -0,0 +1,44 @@
# Generated by Django 2.2.17 on 2021-10-23 16:38
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('media', '0040_auto_20211023_1830'),
]
operations = [
migrations.RenameField(
model_name='game',
old_name='duree',
new_name='duration',
),
migrations.RenameField(
model_name='game',
old_name='proprietaire',
new_name='owner',
),
migrations.RenameField(
model_name='game',
old_name='nombre_joueurs_max',
new_name='players_max',
),
migrations.RenameField(
model_name='game',
old_name='nombre_joueurs_min',
new_name='players_min',
),
migrations.AlterField(
model_name='emprunt',
name='media',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='media.Comic'),
),
migrations.AlterField(
model_name='futuremedium',
name='type',
field=models.CharField(choices=[('bd', 'Comic'), ('manga', 'Manga'), ('roman', 'Roman')], max_length=8, verbose_name='type'),
),
]

View File

@ -9,7 +9,7 @@ from django.utils.translation import gettext_lazy as _
from .fields import ISBNField
class Auteur(models.Model):
class Author(models.Model):
name = models.CharField(
max_length=255,
unique=True,
@ -30,7 +30,7 @@ class Auteur(models.Model):
ordering = ['name']
class BD(models.Model):
class Comic(models.Model):
isbn = ISBNField(
_('ISBN'),
help_text=_('You may be able to scan it from a bar code.'),
@ -61,7 +61,7 @@ class BD(models.Model):
)
authors = models.ManyToManyField(
'Auteur',
'Author',
verbose_name=_('authors'),
)
@ -90,8 +90,8 @@ class BD(models.Model):
return self.title
class Meta:
verbose_name = _("BD")
verbose_name_plural = _("BDs")
verbose_name = _("comic")
verbose_name_plural = _("comics")
ordering = ['title', 'subtitle']
@ -126,7 +126,7 @@ class Manga(models.Model):
)
authors = models.ManyToManyField(
'Auteur',
'Author',
verbose_name=_('authors'),
)
@ -157,7 +157,7 @@ class Manga(models.Model):
ordering = ['title']
class Roman(models.Model):
class Novel(models.Model):
isbn = ISBNField(
_('ISBN'),
help_text=_('You may be able to scan it from a bar code.'),
@ -188,7 +188,7 @@ class Roman(models.Model):
)
authors = models.ManyToManyField(
'Auteur',
'Author',
verbose_name=_('authors'),
)
@ -214,12 +214,12 @@ class Roman(models.Model):
return self.title
class Meta:
verbose_name = _("roman")
verbose_name_plural = _("romans")
verbose_name = _("novel")
verbose_name_plural = _("novels")
ordering = ['title', 'subtitle']
class Vinyle(models.Model):
class Vinyl(models.Model):
title = models.CharField(
verbose_name=_('title'),
max_length=255,
@ -239,7 +239,7 @@ class Vinyle(models.Model):
)
authors = models.ManyToManyField(
'Auteur',
'Author',
verbose_name=_('authors'),
)
@ -253,8 +253,8 @@ class Vinyle(models.Model):
return self.title
class Meta:
verbose_name = _("vinyle")
verbose_name_plural = _("vinyles")
verbose_name = _("vinyl")
verbose_name_plural = _("vinyls")
ordering = ['title']
@ -270,7 +270,7 @@ class CD(models.Model):
)
authors = models.ManyToManyField(
'Auteur',
'Author',
verbose_name=_('authors'),
)
@ -289,7 +289,7 @@ class CD(models.Model):
ordering = ['title']
class Revue(models.Model):
class Review(models.Model):
title = models.CharField(
verbose_name=_('title'),
max_length=255,
@ -335,12 +335,12 @@ class Revue(models.Model):
return self.title + "" + str(self.number)
class Meta:
verbose_name = _("revue")
verbose_name_plural = _("revues")
verbose_name = _("review")
verbose_name_plural = _("reviews")
ordering = ['title', 'number']
class FutureMedia(models.Model):
class FutureMedium(models.Model):
isbn = ISBNField(
_('ISBN'),
help_text=_('You may be able to scan it from a bar code.'),
@ -352,7 +352,7 @@ class FutureMedia(models.Model):
type = models.CharField(
_('type'),
choices=[
('bd', _('BD')),
('bd', _('Comic')),
('manga', _('Manga')),
('roman', _('Roman')),
],
@ -375,7 +375,7 @@ class FutureMedia(models.Model):
class Emprunt(models.Model):
media = models.ForeignKey(
'BD',
'Comic',
on_delete=models.PROTECT,
)
user = models.ForeignKey(
@ -417,8 +417,8 @@ class Emprunt(models.Model):
ordering = ['-date_emprunt']
class Jeu(models.Model):
DUREE = (
class Game(models.Model):
DURATIONS = (
('-1h', '-1h'),
('1-2h', '1-2h'),
('2-3h', '2-3h'),
@ -430,21 +430,21 @@ class Jeu(models.Model):
max_length=255,
verbose_name=_("name"),
)
proprietaire = models.ForeignKey(
owner = models.ForeignKey(
'users.User',
on_delete=models.PROTECT,
verbose_name=_("owner"),
)
duree = models.CharField(
choices=DUREE,
duration = models.CharField(
choices=DURATIONS,
max_length=255,
verbose_name=_("duration"),
)
nombre_joueurs_min = models.IntegerField(
players_min = models.IntegerField(
validators=[MinValueValidator(1)],
verbose_name=_("minimum number of players"),
)
nombre_joueurs_max = models.IntegerField(
players_max = models.IntegerField(
validators=[MinValueValidator(1)],
verbose_name=_('maximum number of players'),
)

View File

@ -4,7 +4,7 @@
import re
import requests
from media.models import Auteur
from media.models import Author
class BedetequeScraper:
@ -44,7 +44,7 @@ class BedetequeScraper:
regex = r'href=\"(https://www\.bedetheque\.com/BD.*.html)\"'
return re.findall(regex, content)
def scrap_bd_info(self, bd_url: str) -> dict:
def scrap_comic_info(self, bd_url: str) -> dict:
"""
Load BD web page and scrap data
:param bd_url: URL where to find BD data
@ -99,12 +99,12 @@ class BedetequeScraper:
if 'author' not in data:
data['authors'] = list()
if author:
author_obj = Auteur.objects.get_or_create(
author_obj = Author.objects.get_or_create(
name=author.group(1))[0]
data['authors'].append(author_obj)
illustrator = re.search(regex_illustrator, content)
if illustrator:
author_obj = Auteur.objects.get_or_create(
author_obj = Author.objects.get_or_create(
name=illustrator.group(1))[0]
data['authors'].append(author_obj)

View File

@ -1,18 +1,18 @@
from rest_framework import serializers
from .models import Auteur, BD, CD, FutureMedia, Manga, Emprunt, Jeu, Revue,\
Roman, Vinyle
from .models import Author, CD, Comic, FutureMedium, Manga, Emprunt, Game, \
Novel, Review, Vinyl
class AuteurSerializer(serializers.ModelSerializer):
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Auteur
model = Author
fields = ['url', 'name']
class BDSerializer(serializers.ModelSerializer):
class ComicSerializer(serializers.ModelSerializer):
class Meta:
model = BD
model = Comic
fields = '__all__'
@ -28,27 +28,27 @@ class CDSerializer(serializers.ModelSerializer):
fields = '__all__'
class VinyleSerializer(serializers.ModelSerializer):
class VinylSerializer(serializers.ModelSerializer):
class Meta:
model = Vinyle
model = Vinyl
fields = '__all__'
class RomanSerializer(serializers.ModelSerializer):
class NovelSerializer(serializers.ModelSerializer):
class Meta:
model = Roman
model = Novel
fields = '__all__'
class RevueSerializer(serializers.ModelSerializer):
class ReviewSerializer(serializers.ModelSerializer):
class Meta:
model = Revue
model = Review
fields = '__all__'
class FutureMediaSerializer(serializers.ModelSerializer):
class FutureMediumSerializer(serializers.ModelSerializer):
class Meta:
model = FutureMedia
model = FutureMedium
fields = '__all__'
@ -59,8 +59,8 @@ class EmpruntSerializer(serializers.HyperlinkedModelSerializer):
'permanencier_emprunt', 'permanencier_rendu']
class JeuSerializer(serializers.HyperlinkedModelSerializer):
class GameSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Jeu
model = Game
fields = ['url', 'name', 'proprietaire', 'duree', 'nombre_joueurs_min',
'nombre_joueurs_max', 'comment']

View File

@ -3,7 +3,7 @@
from django.test import TestCase
from django.urls import reverse
from media.models import Auteur, BD
from media.models import Author, Comic
from users.models import User
"""
@ -21,44 +21,44 @@ class TemplateTests(TestCase):
self.client.force_login(self.user)
# Create an author
self.dummy_author = Auteur.objects.create(name="Test author")
self.dummy_author = Author.objects.create(name="Test author")
# Create media
self.dummy_bd1 = BD.objects.create(
self.dummy_bd1 = Comic.objects.create(
title="Test media",
side_identifier="T M",
)
self.dummy_bd1.authors.add(self.dummy_author)
self.dummy_bd2 = BD.objects.create(
self.dummy_bd2 = Comic.objects.create(
title="Test media bis",
side_identifier="T M 2",
external_url="https://example.com/",
)
self.dummy_bd2.authors.add(self.dummy_author)
def test_bd_bd_changelist(self):
response = self.client.get(reverse('admin:media_bd_changelist'))
def test_comic_bd_changelist(self):
response = self.client.get(reverse('admin:media_comic_changelist'))
self.assertEqual(response.status_code, 200)
def test_bd_bd_add(self):
response = self.client.get(reverse('admin:media_bd_add'))
def test_comic_bd_add(self):
response = self.client.get(reverse('admin:media_comic_add'))
self.assertEqual(response.status_code, 200)
def test_bd_isbn_download(self):
def test_comic_isbn_download(self):
data = {
'_isbn': True,
'isbn': "0316358525",
}
response = self.client.post(reverse(
'admin:media_bd_change',
'admin:media_comic_change',
args=[self.dummy_bd1.id],
), data=data)
self.assertEqual(response.status_code, 302)
def test_bd_emprunt_changelist(self):
def test_comic_emprunt_changelist(self):
response = self.client.get(reverse('admin:media_emprunt_changelist'))
self.assertEqual(response.status_code, 200)
def test_bd_emprunt_add(self):
def test_comic_emprunt_add(self):
response = self.client.get(reverse('admin:media_emprunt_add'))
self.assertEqual(response.status_code, 200)

View File

@ -13,8 +13,8 @@ urlpatterns = [
name='retour-emprunt'),
path('find/', views.FindMediumView.as_view(), name="find"),
path('mark-as-present/bd/<int:pk>/',
views.MarkBDAsPresent.as_view(),
name="mark_bd_as_present"),
views.MarkComicAsPresent.as_view(),
name="mark_comic_as_present"),
path('mark-as-present/manga/<int:pk>/',
views.MarkMangaAsPresent.as_view(),
name="mark_manga_as_present"),
@ -22,7 +22,7 @@ urlpatterns = [
views.MarkCDAsPresent.as_view(),
name="mark_cd_as_present"),
path('mark-as-present/vinyle/<int:pk>/',
views.MarkVinyleAsPresent.as_view(),
views.MarkVinylAsPresent.as_view(),
name="mark_vinyle_as_present"),
path('mark-as-present/roman/<int:pk>/',
views.MarkRomanAsPresent.as_view(),

View File

@ -8,7 +8,7 @@ from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponse
from django_filters.rest_framework import DjangoFilterBackend
from django.db import transaction
from django.shortcuts import redirect, render
from django.shortcuts import redirect
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from django.views.generic import TemplateView, DetailView
@ -16,11 +16,11 @@ from rest_framework import viewsets
from rest_framework.filters import SearchFilter
from reversion import revisions as reversion
from .models import Auteur, BD, CD, Emprunt, FutureMedia, Jeu, Manga, Revue,\
Roman, Vinyle
from .serializers import AuteurSerializer, BDSerializer, CDSerializer,\
EmpruntSerializer, FutureMediaSerializer, JeuSerializer, MangaSerializer,\
RevueSerializer, RomanSerializer, VinyleSerializer
from .models import Author, CD, Comic, Emprunt, FutureMedium, Game, Manga,\
Novel, Review, Vinyl
from .serializers import AuthorSerializer, ComicSerializer, CDSerializer,\
EmpruntSerializer, FutureMediumSerializer, GameSerializer, \
MangaSerializer, NovelSerializer, ReviewSerializer, VinylSerializer
@login_required
@ -40,16 +40,17 @@ def retour_emprunt(request, empruntid):
return redirect("admin:media_emprunt_changelist")
def index(request):
class IndexView(TemplateView):
"""
Home page which redirect to admin when logged in
"""
extra_context = {'title': _('Welcome to the Mediatek database')}
template_name = 'admin/index.html'
def dispatch(self, request, *args, **kwargs):
if request.user.is_authenticated:
return redirect('admin:index')
else:
return render(request, 'admin/index.html', {
'title': _('Welcome to the Mediatek database'),
})
return super().dispatch(request, *args, **kwargs)
class FindMediumView(LoginRequiredMixin, TemplateView):
@ -64,8 +65,8 @@ class MarkMediumAsPresent(LoginRequiredMixin, DetailView):
return HttpResponse("", content_type=204)
class MarkBDAsPresent(MarkMediumAsPresent):
model = BD
class MarkComicAsPresent(MarkMediumAsPresent):
model = Comic
class MarkMangaAsPresent(MarkMediumAsPresent):
@ -76,36 +77,36 @@ class MarkCDAsPresent(MarkMediumAsPresent):
model = CD
class MarkVinyleAsPresent(MarkMediumAsPresent):
model = Vinyle
class MarkVinylAsPresent(MarkMediumAsPresent):
model = Vinyl
class MarkRomanAsPresent(MarkMediumAsPresent):
model = Roman
model = Novel
class MarkRevueAsPresent(MarkMediumAsPresent):
model = Revue
model = Review
class MarkFutureAsPresent(MarkMediumAsPresent):
model = FutureMedia
model = FutureMedium
class AuteurViewSet(viewsets.ModelViewSet):
class AuthorViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows authors to be viewed or edited.
"""
queryset = Auteur.objects.all()
serializer_class = AuteurSerializer
queryset = Author.objects.all()
serializer_class = AuthorSerializer
class BDViewSet(viewsets.ModelViewSet):
class ComicViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows media to be viewed or edited.
"""
queryset = BD.objects.all()
serializer_class = BDSerializer
queryset = Comic.objects.all()
serializer_class = ComicSerializer
filter_backends = [DjangoFilterBackend, SearchFilter]
filterset_fields = ["isbn", "side_identifier"]
search_fields = ["=isbn", "title", "subtitle", "side_identifier",
@ -135,46 +136,46 @@ class CDViewSet(viewsets.ModelViewSet):
search_fields = ["title", "side_identifier", "authors__name"]
class VinyleViewSet(viewsets.ModelViewSet):
class VinylViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows media to be viewed or edited.
"""
queryset = Vinyle.objects.all()
serializer_class = VinyleSerializer
queryset = Vinyl.objects.all()
serializer_class = VinylSerializer
filter_backends = [DjangoFilterBackend, SearchFilter]
filterset_fields = ["side_identifier", "rpm"]
search_fields = ["title", "side_identifier", "authors__name"]
class RomanViewSet(viewsets.ModelViewSet):
class NovelViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows media to be viewed or edited.
"""
queryset = Roman.objects.all()
serializer_class = RomanSerializer
queryset = Novel.objects.all()
serializer_class = NovelSerializer
filter_backends = [DjangoFilterBackend, SearchFilter]
filterset_fields = ["isbn", "side_identifier", "number_of_pages"]
search_fields = ["=isbn", "title", "subtitle", "side_identifier",
"authors__name"]
class RevueViewSet(viewsets.ModelViewSet):
class ReviewViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows media to be viewed or edited.
"""
queryset = Revue.objects.all()
serializer_class = RevueSerializer
queryset = Review.objects.all()
serializer_class = ReviewSerializer
filter_backends = [DjangoFilterBackend, SearchFilter]
filterset_fields = ["number", "year", "month", "day", "double"]
search_fields = ["title"]
class FutureMediaViewSet(viewsets.ModelViewSet):
class FutureMediumViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows media to be viewed or edited.
"""
queryset = FutureMedia.objects.all()
serializer_class = FutureMediaSerializer
queryset = FutureMedium.objects.all()
serializer_class = FutureMediumSerializer
filter_backends = [DjangoFilterBackend, SearchFilter]
filterset_fields = ["isbn"]
search_fields = ["=isbn"]
@ -188,9 +189,9 @@ class EmpruntViewSet(viewsets.ModelViewSet):
serializer_class = EmpruntSerializer
class JeuViewSet(viewsets.ModelViewSet):
class GameViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows games to be viewed or edited.
"""
queryset = Jeu.objects.all()
serializer_class = JeuSerializer
queryset = Game.objects.all()
serializer_class = GameSerializer

View File

@ -1,13 +1,7 @@
Django~=2.2.10
docutils~=0.14
Pillow>=8.0.1
pytz~=2020.4
six~=1.15
sqlparse~=0.3
docutils~=0.16 # for Django-admin docs
Django~=2.2
django-filter~=2.4
django-reversion~=3.0
python-stdnum~=1.14
djangorestframework~=3.12.1
pyyaml~=5.3.1
coreapi~=2.3.3
django_extensions~=3.1
djangorestframework~=3.12
django_extensions~=3.0
requests~=2.25 # for scrapping

View File

@ -13,12 +13,7 @@ from reversion.admin import VersionAdmin
from med.admin import admin_site
from .forms import UserCreationAdminForm
from .models import Adhesion, User
class AdhesionAdmin(VersionAdmin):
list_display = ('starting_in', 'ending_in')
autocomplete_fields = ('members',)
from .models import User
class IsMemberFilter(admin.SimpleListFilter):
@ -31,12 +26,7 @@ class IsMemberFilter(admin.SimpleListFilter):
)
def queryset(self, request, queryset):
value = self.value()
if value == 'Yes':
# Get current membership year and list all members
last_adh_year = Adhesion.objects.all().order_by('starting_in') \
.reverse().first()
return last_adh_year.members
# FIXME Replace with imported Note Kfet memberships
return queryset
@ -88,9 +78,8 @@ class UserAdmin(VersionAdmin, BaseUserAdmin):
"""
Get current membership year and check if user is there
"""
last_adh_year = Adhesion.objects.all().order_by('starting_in') \
.reverse().first()
is_member = last_adh_year and obj in last_adh_year.members.all()
# FIXME Use NK20
is_member = True
if is_member:
return format_html(
'<img src="/static/admin/img/icon-yes.svg" alt="True">'
@ -108,4 +97,3 @@ class UserAdmin(VersionAdmin, BaseUserAdmin):
admin_site.register(User, UserAdmin)
admin_site.register(Adhesion, AdhesionAdmin)

View File

@ -0,0 +1,16 @@
# Generated by Django 2.2.17 on 2021-10-23 12:48
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('users', '0041_auto_20200923_2030'),
]
operations = [
migrations.DeleteModel(
name='Adhesion',
),
]

View File

@ -42,31 +42,5 @@ class User(AbstractUser):
@property
def is_member(self):
last_year = Adhesion.objects.all().order_by(
'starting_in').reverse().first()
return last_year and self in last_year.members.all()
class Adhesion(models.Model):
starting_in = models.IntegerField(
verbose_name=_('starting in'),
help_text=_('Year in which the membership year starts.'),
unique=True,
)
ending_in = models.IntegerField(
verbose_name=_('ending in'),
help_text=_('Year in which the membership year ends.'),
unique=True,
)
members = models.ManyToManyField(
'User',
verbose_name=_('members'),
blank=True,
)
class Meta:
verbose_name = _('membership year')
verbose_name_plural = _('membership years')
def __str__(self):
return f"{self.starting_in} - {self.ending_in}"
# FIXME Use NK20
return True

View File

@ -9,5 +9,4 @@ from . import views
app_name = 'users'
urlpatterns = [
url(r'^edit_info/$', views.edit_info, name='edit-info'),
url(r'^adherer/(?P<userid>[0-9]+)$', views.adherer, name='adherer'),
]

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
from django.contrib import messages
from django.contrib.auth.decorators import login_required, permission_required
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import Group
from django.db import transaction
from django.shortcuts import redirect, render
@ -12,7 +12,7 @@ from django.utils.translation import ugettext_lazy as _
from rest_framework import viewsets
from reversion import revisions as reversion
from users.forms import BaseInfoForm
from users.models import Adhesion, User
from users.models import User
from .serializers import GroupSerializer, UserSerializer
@ -44,27 +44,6 @@ def edit_info(request):
}, 'users/user.html', request)
@login_required
@permission_required('users.add_adhesion')
def adherer(request, userid):
try:
users = User.objects.get(pk=userid)
except User.DoesNotExist:
messages.error(request, "Utilisateur inexistant")
return redirect("admin:users_user_changelist")
adh_year = Adhesion.objects.all().order_by('starting_in').reverse().first()
if not adh_year:
messages.error(request, "Année d'adhésion non définie")
return redirect("admin:users_user_changelist")
with transaction.atomic(), reversion.create_revision():
reversion.set_user(request.user)
adh_year.members.add(users)
adh_year.save()
reversion.set_comment("Adhesion de %s" % users)
messages.success(request, "Adhesion effectuee")
return redirect("admin:users_user_changelist")
class UserViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.