Catalogue: wikidata suggestions
[redakcja.git] / src / catalogue / views.py
1 # This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later.
2 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
3 #
4 from django.apps import apps
5 from django.db.models import Prefetch
6 from django.http import Http404
7 from django.utils.formats import localize_input
8 from django.contrib.auth.models import User
9 from django.views.generic import DetailView, TemplateView
10 from . import models
11 import documents.models
12 from rest_framework.generics import ListAPIView
13 from rest_framework.filters import SearchFilter
14 from rest_framework.permissions import IsAdminUser
15 from rest_framework.response import Response
16 from rest_framework.views import APIView
17 from rest_framework import serializers
18
19
20 class CatalogueView(TemplateView):
21     template_name = "catalogue/catalogue.html"
22
23     def get_context_data(self):
24         ctx = super().get_context_data()
25         ctx["authors"] = models.Author.objects.all().prefetch_related('book_set__book_set', 'translated_book_set__book_set')
26
27         return ctx
28
29
30 class AuthorView(TemplateView):
31     model = models.Author
32     template_name = "catalogue/author_detail.html"
33
34     def get_context_data(self, slug):
35         ctx = super().get_context_data()
36         authors = models.Author.objects.filter(slug=slug).prefetch_related(
37             Prefetch("book_set"),
38             Prefetch("translated_book_set"),
39         )
40         ctx["author"] = authors.first()
41         return ctx
42
43
44 class BookView(DetailView):
45     model = models.Book
46
47
48 class TermSearchFilter(SearchFilter):
49     search_param = 'term'
50
51
52 class Terms(ListAPIView):
53     filter_backends = [TermSearchFilter]
54     search_fields = ['name']
55
56     class serializer_class(serializers.Serializer):
57         label = serializers.CharField(source='name')
58
59
60 class EpochTerms(Terms):
61     queryset = models.Epoch.objects.all()
62 class KindTerms(Terms):
63     queryset = models.Kind.objects.all()
64 class GenreTerms(Terms):
65     queryset = models.Genre.objects.all()
66
67 class AuthorTerms(Terms):
68     search_fields = ['first_name', 'last_name']
69     queryset = models.Author.objects.all()
70
71 class EditorTerms(Terms):
72     search_fields = ['first_name', 'last_name', 'username']
73     queryset = User.objects.all()
74
75     class serializer_class(serializers.Serializer):
76         label = serializers.SerializerMethodField()
77
78         def get_label(self, obj):
79             return f'{obj.last_name}, {obj.first_name}'
80     
81 class BookTitleTerms(Terms):
82     queryset = models.Book.objects.all()
83     search_fields = ['title', 'slug']
84
85     class serializer_class(serializers.Serializer):
86         label = serializers.CharField(source='title')
87
88 class WLURITerms(Terms):
89     queryset = models.Book.objects.all()
90     search_fields = ['title', 'slug']
91     
92     class serializer_class(serializers.Serializer):
93         label = serializers.CharField(source='wluri')
94
95
96 class WikidataView(APIView):
97     permission_classes = [IsAdminUser]
98
99     def get_object(self, model, qid, save):
100         try:
101             Model = apps.get_model('catalogue', model)
102         except LookupError:
103             raise Http404
104         if not issubclass(Model, models.WikidataModel):
105             raise Http404
106
107         obj = Model.objects.filter(wikidata=qid).first()
108         if obj is None:
109             obj = Model(wikidata=qid)
110         if not obj.pk and save:
111             obj.save()
112         else:
113             obj.wikidata_populate(save=False)
114         d = {
115             "id": obj.pk,
116         }
117         for attname in dir(Model.Wikidata):
118             if attname.startswith("_"):
119                 continue
120             for fieldname, lang in obj.wikidata_fields_for_attribute(attname):
121                 d[fieldname] = getattr(obj, fieldname)
122
123                 if isinstance(d[fieldname], models.WikidataModel):
124                     d[attname] = {
125                         "model": type(d[fieldname])._meta.model_name,
126                         "wd": d[fieldname].wikidata,
127                         "label": str(d[fieldname]) or d[fieldname]._wikidata_label,
128                     }
129                 else:
130                     d[fieldname] = localize_input(d[fieldname])
131         return Response(d)
132     
133     def get(self, request, model, qid):
134         return self.get_object(model, qid, save=False)
135
136     def post(self, request, model, qid):
137         return self.get_object(model, qid, save=True)