From: Radek Czajka Date: Wed, 8 Oct 2025 12:43:07 +0000 (+0200) Subject: Merge branch 'master' into appdev X-Git-Url: https://git.mdrn.pl/wolnelektury.git/commitdiff_plain/102acc0b6eb715826f26b5082611604cf6ebe240?ds=sidebyside;hp=--cc Merge branch 'master' into appdev --- 102acc0b6eb715826f26b5082611604cf6ebe240 diff --cc src/catalogue/api/urls2.py index 29d4a3a0e,e90e13eea..ad96d7a51 --- a/src/catalogue/api/urls2.py +++ b/src/catalogue/api/urls2.py @@@ -23,9 -23,9 +23,11 @@@ urlpatterns = piwik_track_view(views.BookFragmentView.as_view()), name='catalogue_api_book_fragment' ), - path('books//media//', views.BookMediaView.as_view()), + path('books//media//', + views.BookMediaView.as_view() + ), + path('books/.json', + views.BookJsonView.as_view()), path('suggested-tags/', piwik_track_view(views.SuggestedTags.as_view()), diff --cc src/catalogue/api/views.py index 198f87fdd,821b281c4..ed5d10f1d --- a/src/catalogue/api/views.py +++ b/src/catalogue/api/views.py @@@ -537,15 -523,7 +537,17 @@@ class BookMediaView(ListAPIView) pagination_class = None def get_queryset(self): - return BookMedia.objects.filter(book__slug=self.kwargs['slug'], type=self.kwargs['type']).order_by('index') + return BookMedia.objects.filter( + book__slug=self.kwargs['slug'], + type=self.kwargs['type'] + ).order_by('index') + + +from .tojson import conv +from lxml import etree +from rest_framework.views import APIView +class BookJsonView(APIView): + def get(self, request, slug): + book = get_object_or_404(Book, slug=slug) + js = conv(etree.parse(book.xml_file.path)) + return JsonResponse(js, json_dumps_params={'ensure_ascii': False}) - diff --cc src/catalogue/models/book.py index 0f53baf0c,0400656e2..b2148e6b4 --- a/src/catalogue/models/book.py +++ b/src/catalogue/models/book.py @@@ -92,8 -94,10 +94,10 @@@ class Book(models.Model) objects = models.Manager() tagged = managers.ModelTaggedItemManager(Tag) tags = managers.TagDescriptor(Tag) - tag_relations = GenericRelation(Tag.intermediary_table_model) + tag_relations = GenericRelation(Tag.intermediary_table_model, related_query_name='tagged_book') translators = models.ManyToManyField(Tag, blank=True) + narrators = models.ManyToManyField(Tag, blank=True, related_name='narrated') + has_audio = models.BooleanField(default=False) html_built = django.dispatch.Signal() published = django.dispatch.Signal() diff --cc src/catalogue/views.py index a56286de7,d5b83ab08..1ac6c089d --- a/src/catalogue/views.py +++ b/src/catalogue/views.py @@@ -238,16 -225,12 +238,17 @@@ class TaggedObjectList(BookList) t for t in self.ctx['tags'] if t is not self.ctx['main_tag'] ] - if len(self.ctx['tags']) == 1 and self.ctx['main_tag'].category == 'author': + if len(self.ctx['tags']) == 1 and self.ctx['main_tag'] is not None and self.ctx['main_tag'].category == 'author': self.ctx['translation_list'] = self.ctx['main_tag'].book_set.all() + self.ctx['narrated'] = self.ctx['main_tag'].narrated.all() def get_queryset(self): - qs = Book.tagged.with_all(self.ctx['work_tags']).filter(findable=True) + if self.ctx['work_tags']: + qs = Book.tagged.with_all(self.ctx['work_tags']).filter(findable=True) + else: + qs = Book.objects.filter(findable=True) + for ul in self.ctx['user_lists']: + qs = qs.filter(id__in=[i.id for i in ul.get_books()]) qs = qs.exclude(ancestor__in=qs) if self.is_themed: fqs = Fragment.tagged.with_all(self.ctx['fragment_tags']) diff --cc src/social/views.py index e3d60ca93,8f27b8746..0ff077104 --- a/src/social/views.py +++ b/src/social/views.py @@@ -18,13 -19,14 +18,14 @@@ from wolnelektury.utils import is_aja # ==================== - @require_POST + @login_required def like_book(request, slug): - if not request.user.is_authenticated: - return HttpResponseForbidden('Login required.') book = get_object_or_404(Book, slug=slug) + if request.method != 'POST': + return redirect(book) + - book.like(request.user) + models.UserList.like(request.user, book) if is_ajax(request): return JsonResponse({"success": True, "msg": "ok", "like": True}) @@@ -49,13 -51,14 +50,14 @@@ class RemoveSetView(AddSetView) form_class = forms.RemoveSetForm - @require_POST + @login_required def unlike_book(request, slug): - if not request.user.is_authenticated: - return HttpResponseForbidden('Login required.') book = get_object_or_404(Book, slug=slug) + if request.method != 'POST': + return redirect(book) + - book.unlike(request.user) + models.UserList.unlike(request.user, book) if is_ajax(request): return JsonResponse({"success": True, "msg": "ok", "like": False})