X-Git-Url: https://git.mdrn.pl/redakcja.git/blobdiff_plain/acf3c41fb0ffe8e451b1e465b00e9998f2b027ac..4b200d823f0ec79279da035a46d0d888693ca2fe:/src/catalogue/views.py diff --git a/src/catalogue/views.py b/src/catalogue/views.py index 0b29b6f4..376d3287 100644 --- a/src/catalogue/views.py +++ b/src/catalogue/views.py @@ -1,10 +1,25 @@ # This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later. # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # +from django.apps import apps from django.db.models import Prefetch +from django.http import Http404 +from django.urls import reverse +from django.utils.formats import localize_input +from django.contrib.auth.decorators import login_required +from django.contrib.auth.models import User +from django.shortcuts import get_object_or_404, redirect +from django.views.decorators.http import require_POST from django.views.generic import DetailView, TemplateView +import apiclient from . import models import documents.models +from rest_framework.generics import ListAPIView, RetrieveAPIView +from rest_framework.filters import SearchFilter +from rest_framework.permissions import IsAdminUser +from rest_framework.response import Response +from rest_framework.views import APIView +from rest_framework import serializers class CatalogueView(TemplateView): @@ -12,13 +27,8 @@ class CatalogueView(TemplateView): def get_context_data(self): ctx = super().get_context_data() - documents_books_queryset = models.Book.objects.prefetch_unrelated( - "document_books", "slug", documents.models.Book, "dc_slug" - ) - ctx["authors"] = models.Author.objects.all().prefetch_related( - Prefetch("book_set", queryset=documents_books_queryset), - Prefetch("translated_book_set", queryset=documents_books_queryset), - ) + ctx["authors"] = models.Author.objects.all().prefetch_related('book_set__book_set', 'translated_book_set__book_set') + return ctx @@ -28,12 +38,9 @@ class AuthorView(TemplateView): def get_context_data(self, slug): ctx = super().get_context_data() - documents_books_queryset = models.Book.objects.prefetch_unrelated( - "document_books", "slug", documents.models.Book, "dc_slug" - ) authors = models.Author.objects.filter(slug=slug).prefetch_related( - Prefetch("book_set", queryset=documents_books_queryset), - Prefetch("translated_book_set", queryset=documents_books_queryset), + Prefetch("book_set"), + Prefetch("translated_book_set"), ) ctx["author"] = authors.first() return ctx @@ -41,3 +48,163 @@ class AuthorView(TemplateView): class BookView(DetailView): model = models.Book + +class BookAPIView(RetrieveAPIView): + queryset = models.Book.objects.all() + lookup_field = 'slug' + + class serializer_class(serializers.ModelSerializer): + class AuthorSerializer(serializers.ModelSerializer): + literal = serializers.CharField(source='name') + + class Meta: + model = models.Author + fields = ['literal'] + + def category_serializer(m): + class CategorySerializer(serializers.ModelSerializer): + literal = serializers.CharField(source='name') + class Meta: + model = m + fields = ['literal'] + return CategorySerializer + + authors = AuthorSerializer(many=True) + translators = AuthorSerializer(many=True) + epochs = category_serializer(models.Epoch)(many=True) + kinds = category_serializer(models.Kind)(many=True) + genres = category_serializer(models.Genre)(many=True) + + class Meta: + model = models.Book + fields = [ + 'title', + 'authors', + 'translators', + 'epochs', + 'kinds', + 'genres', + 'scans_source', + 'text_source', + 'original_year', + 'pd_year', + ] + + +class TermSearchFilter(SearchFilter): + search_param = 'term' + + +class Terms(ListAPIView): + filter_backends = [TermSearchFilter] + search_fields = ['name'] + + class serializer_class(serializers.Serializer): + label = serializers.CharField(source='name') + + +class EpochTerms(Terms): + queryset = models.Epoch.objects.all() +class KindTerms(Terms): + queryset = models.Kind.objects.all() +class GenreTerms(Terms): + queryset = models.Genre.objects.all() + +class AuthorTerms(Terms): + search_fields = ['first_name', 'last_name'] + queryset = models.Author.objects.all() + +class EditorTerms(Terms): + search_fields = ['first_name', 'last_name', 'username'] + queryset = User.objects.all() + + class serializer_class(serializers.Serializer): + label = serializers.SerializerMethodField() + + def get_label(self, obj): + return f'{obj.last_name}, {obj.first_name}' + +class BookTitleTerms(Terms): + queryset = models.Book.objects.all() + search_fields = ['title', 'slug'] + + class serializer_class(serializers.Serializer): + label = serializers.CharField(source='title') + +class WLURITerms(Terms): + queryset = models.Book.objects.all() + search_fields = ['title', 'slug'] + + class serializer_class(serializers.Serializer): + label = serializers.CharField(source='wluri') + + +class WikidataView(APIView): + permission_classes = [IsAdminUser] + + def get_object(self, model, qid, save): + try: + Model = apps.get_model('catalogue', model) + except LookupError: + raise Http404 + if not issubclass(Model, models.WikidataModel): + raise Http404 + + obj = Model.objects.filter(wikidata=qid).first() + if obj is None: + obj = Model(wikidata=qid) + if not obj.pk and save: + obj.save() + else: + obj.wikidata_populate(save=False, force=True) + d = { + "id": obj.pk, + "__str__": str(obj), + } + for attname in dir(Model.Wikidata): + if attname.startswith("_"): + continue + for fieldname, lang in obj.wikidata_fields_for_attribute(attname): + d[fieldname] = getattr(obj, fieldname) + + if isinstance(d[fieldname], models.WikidataModel): + d[fieldname] = { + "model": type(d[fieldname])._meta.model_name, + "id": d[fieldname].pk, + "wd": d[fieldname].wikidata, + "label": str(d[fieldname]) or d[fieldname]._wikidata_label, + } + elif hasattr(d[fieldname], 'all'): + d[fieldname] = [ + { + "model": type(item)._meta.model_name, + "wd": item.wikidata, + "label": str(item) or item._wikidata_label + } for item in d[fieldname].all() + ] + elif hasattr(d[fieldname], 'as_hint_json'): + d[fieldname] = d[fieldname].as_hint_json() + elif hasattr(d[fieldname], 'storage'): + d[fieldname] = d[fieldname].url if d[fieldname] else None + else: + d[fieldname] = localize_input(d[fieldname]) + return Response(d) + + def get(self, request, model, qid): + return self.get_object(model, qid, save=False) + + def post(self, request, model, qid): + return self.get_object(model, qid, save=True) + + +@require_POST +@login_required +def publish_author(request, pk): + author = get_object_or_404(models.Author, pk=pk) + data = { + "description_pl": author.generate_description(), + } + apiclient.api_call(request.user, f"authors/{author.slug}/", data) + return redirect(reverse('admin:catalogue_author_change', args=[author.pk])) + +