Author description generator
[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.urls import reverse
8 from django.utils.formats import localize_input
9 from django.contrib.auth.decorators import login_required
10 from django.contrib.auth.models import User
11 from django.shortcuts import get_object_or_404, redirect
12 from django.views.decorators.http import require_POST
13 from django.views.generic import DetailView, TemplateView
14 import apiclient
15 from . import models
16 import documents.models
17 from rest_framework.generics import ListAPIView
18 from rest_framework.filters import SearchFilter
19 from rest_framework.permissions import IsAdminUser
20 from rest_framework.response import Response
21 from rest_framework.views import APIView
22 from rest_framework import serializers
23
24
25 class CatalogueView(TemplateView):
26     template_name = "catalogue/catalogue.html"
27
28     def get_context_data(self):
29         ctx = super().get_context_data()
30         ctx["authors"] = models.Author.objects.all().prefetch_related('book_set__book_set', 'translated_book_set__book_set')
31
32         return ctx
33
34
35 class AuthorView(TemplateView):
36     model = models.Author
37     template_name = "catalogue/author_detail.html"
38
39     def get_context_data(self, slug):
40         ctx = super().get_context_data()
41         authors = models.Author.objects.filter(slug=slug).prefetch_related(
42             Prefetch("book_set"),
43             Prefetch("translated_book_set"),
44         )
45         ctx["author"] = authors.first()
46         return ctx
47
48
49 class BookView(DetailView):
50     model = models.Book
51
52
53 class TermSearchFilter(SearchFilter):
54     search_param = 'term'
55
56
57 class Terms(ListAPIView):
58     filter_backends = [TermSearchFilter]
59     search_fields = ['name']
60
61     class serializer_class(serializers.Serializer):
62         label = serializers.CharField(source='name')
63
64
65 class EpochTerms(Terms):
66     queryset = models.Epoch.objects.all()
67 class KindTerms(Terms):
68     queryset = models.Kind.objects.all()
69 class GenreTerms(Terms):
70     queryset = models.Genre.objects.all()
71
72 class AuthorTerms(Terms):
73     search_fields = ['first_name', 'last_name']
74     queryset = models.Author.objects.all()
75
76 class EditorTerms(Terms):
77     search_fields = ['first_name', 'last_name', 'username']
78     queryset = User.objects.all()
79
80     class serializer_class(serializers.Serializer):
81         label = serializers.SerializerMethodField()
82
83         def get_label(self, obj):
84             return f'{obj.last_name}, {obj.first_name}'
85     
86 class BookTitleTerms(Terms):
87     queryset = models.Book.objects.all()
88     search_fields = ['title', 'slug']
89
90     class serializer_class(serializers.Serializer):
91         label = serializers.CharField(source='title')
92
93 class WLURITerms(Terms):
94     queryset = models.Book.objects.all()
95     search_fields = ['title', 'slug']
96     
97     class serializer_class(serializers.Serializer):
98         label = serializers.CharField(source='wluri')
99
100
101 class WikidataView(APIView):
102     permission_classes = [IsAdminUser]
103
104     def get_object(self, model, qid, save):
105         try:
106             Model = apps.get_model('catalogue', model)
107         except LookupError:
108             raise Http404
109         if not issubclass(Model, models.WikidataModel):
110             raise Http404
111
112         obj = Model.objects.filter(wikidata=qid).first()
113         if obj is None:
114             obj = Model(wikidata=qid)
115         if not obj.pk and save:
116             obj.save()
117         else:
118             obj.wikidata_populate(save=False)
119         d = {
120             "id": obj.pk,
121         }
122         for attname in dir(Model.Wikidata):
123             if attname.startswith("_"):
124                 continue
125             for fieldname, lang in obj.wikidata_fields_for_attribute(attname):
126                 d[fieldname] = getattr(obj, fieldname)
127
128                 if isinstance(d[fieldname], models.WikidataModel):
129                     d[attname] = {
130                         "model": type(d[fieldname])._meta.model_name,
131                         "wd": d[fieldname].wikidata,
132                         "label": str(d[fieldname]) or d[fieldname]._wikidata_label,
133                     }
134                 elif hasattr(d[fieldname], 'all'):
135                     d[attname] = [
136                             {"model": type(item)._meta.model_name,
137                                 "wd": item.wikidata,
138                                 "label": str(item) or item._wikidata_label
139                                 } for item in d[attname].all()
140                             ]
141                 else:
142                     d[fieldname] = localize_input(d[fieldname])
143         return Response(d)
144     
145     def get(self, request, model, qid):
146         return self.get_object(model, qid, save=False)
147
148     def post(self, request, model, qid):
149         return self.get_object(model, qid, save=True)
150
151
152 @require_POST
153 @login_required
154 def publish_author(request, pk):
155     author = get_object_or_404(models.Author, pk=pk)
156     data = {
157         "description_pl": author.generate_description(),
158     }
159     apiclient.api_call(request.user, f"authors/{author.slug}/", data)
160     return redirect(reverse('admin:catalogue_author_change', args=[author.pk]))
161         
162