Loading opds_catalog/feeds.py +82 −48 Original line number Diff line number Diff line from itertools import chain from opds_catalog.sviews import Feed #from itertools import chain from django.utils import timezone from django.utils.translation import ugettext as _ from django.utils.feedgenerator import Atom1Feed, Enclosure, rfc3339_date from django.contrib.syndication.views import Feed #from django.contrib.syndication.views import Feed from django.core.urlresolvers import reverse from django.core.paginator import Paginator, EmptyPage from django.shortcuts import render from django.db.models import Count, Min, Sum from django.db.models import Count, Min from opds_catalog.models import Book, Catalog, Author, Genre, Series, bookshelf, Counter, lang_menu from opds_catalog import models from opds_catalog import settings from opds_catalog.opds_middleware import BasicAuthMiddleware from opds_catalog.opds_paginator import Paginator as OPDS_Paginator import time class AuthFeed(Feed): request = None Loading Loading @@ -197,38 +201,66 @@ class MainFeed(AuthFeed): class CatalogsFeed(AuthFeed): feed_type = opdsFeed subtitle = settings.SUBTITLE description_template = "book_description_cat.html" ##description_template = "book_description.html" def get_object(self, request, cat_id=None, page=1): print('get_object', time.time()) if not isinstance(page, int): page = int(page) try: if cat_id is not None: return (Catalog.objects.get(id=cat_id), page) cat = Catalog.objects.get(id=cat_id) else: return (Catalog.objects.get(parent__id=cat_id), page) cat = Catalog.objects.get(parent__id=cat_id) except Catalog.DoesNotExist: cat = None catalogs_list = Catalog.objects.filter(parent=cat).order_by("cat_name") catalogs_count = catalogs_list.count() # prefetch_related on sqlite on items >999 therow error "too many SQL variables" #books_list = Book.objects.filter(catalog=cat).prefetch_related('authors','genres','series').order_by("title") books_list = Book.objects.filter(catalog=cat).order_by("search_title") books_count = books_list.count() # Получаем результирующий список op = OPDS_Paginator(catalogs_count, books_count, page, settings.MAXITEMS) items = [] for row in catalogs_list[op.d1_first_pos:op.d1_last_pos]: p = {'is_catalog':1, 'title': row.cat_name,'id': row.id, 'cat_type':row.cat_type, 'parent_id':row.parent_id} items.append(p) for row in books_list[op.d2_first_pos:op.d2_last_pos]: p = {'is_catalog':0, 'lang_code': row.lang_code, 'filename': row.filename, 'path': row.path, \ 'registerdate': row.registerdate, 'id': row.id, 'annotation': row.annotation, \ 'docdate': row.docdate, 'format': row.format, 'title': row.title, 'filesize': row.filesize//1000, 'authors':row.authors.values(), 'genres':row.genres.values(), 'series':row.series.values()} items.append(p) return items, cat, op.get_data_dict() def title(self, obj): cat, current_page = obj items, cat, paginator = obj if cat.parent: return "%s | %s | %s"%(settings.TITLE,_("By catalogs"), cat.path) else: return "%s | %s"%(settings.TITLE,_("By catalogs")) def link(self, obj): cat, current_page = obj return reverse("opds_catalog:cat_page", kwargs={"cat_id":cat.id, "page":current_page}) items, cat, paginator = obj return reverse("opds_catalog:cat_page", kwargs={"cat_id":cat.id, "page":paginator['number']}) def feed_extra_kwargs(self, obj): cat, current_page = obj items, cat, paginator = obj start_url = reverse("opds_catalog:main") if current_page != 1: prev_url = reverse("opds_catalog:cat_page", kwargs={"cat_id":cat.id,"page":(current_page-1)}) if paginator['has_previos']: prev_url = reverse("opds_catalog:cat_page", kwargs={"cat_id":cat.id,"page":paginator['previous_page_number']}) else: prev_url = None if current_page*settings.MAXITEMS<Catalog.objects.filter(parent=cat).count() + Book.objects.filter(catalog=cat).count(): next_url = reverse("opds_catalog:cat_page", kwargs={"cat_id":cat.id,"page":(current_page+1)}) if paginator['has_next']: next_url = reverse("opds_catalog:cat_page", kwargs={"cat_id":cat.id,"page":paginator['next_page_number']}) else: next_url = None Loading @@ -240,49 +272,51 @@ class CatalogsFeed(AuthFeed): } def items(self, obj): cat, current_page = obj catalogs_list = Catalog.objects.filter(parent=cat).order_by("cat_name") # prefetch_related on sqlite on items >999 therow error "too many SQL variables" #books_list = Book.objects.filter(catalog=cat).prefetch_related('authors','genres','series').order_by("title") books_list = Book.objects.filter(catalog=cat).order_by("search_title") union_list = list(chain(catalogs_list,books_list)) paginator = Paginator(union_list,settings.MAXITEMS) try: page = paginator.page(current_page) except EmptyPage: page = paginator.page(paginator.num_pages) return page items, cat, paginator = obj print('items', time.time()) return items def item_title(self, item): if isinstance(item, Catalog): return item.cat_name else: return item.title return item['title'] def item_guid(self, item): if isinstance(item, Catalog): gp = 'c:' else: gp = 'b:' return "%s%s"%(gp,item.id) gp = 'c:' if item['is_catalog'] else 'b:' return "%s%s"%(gp,item['id']) def item_link(self, item): if isinstance(item, Catalog): return reverse("opds_catalog:cat_tree", kwargs={"cat_id":item.id}) if item['is_catalog']: return reverse("opds_catalog:cat_tree", kwargs={"cat_id":item['id']}) else: return reverse("opds_catalog:download", kwargs={"book_id":item.id,"zip_flag":0}) return reverse("opds_catalog:download", kwargs={"book_id":item['id'],"zip_flag":0}) def item_enclosures(self, item): if isinstance(item, Catalog): return (opdsEnclosure(reverse("opds_catalog:cat_tree", kwargs={"cat_id":item.id}),"application/atom+xml;profile=opds-catalog;kind=navigation", "subsection"),) if item['is_catalog']: return (opdsEnclosure(reverse("opds_catalog:cat_tree", kwargs={"cat_id":item['id']}),"application/atom+xml;profile=opds-catalog;kind=navigation", "subsection"),) else: return ( opdsEnclosure(reverse("opds_catalog:download", kwargs={"book_id":item.id,"zip_flag":0}),"application/fb2" ,"http://opds-spec.org/acquisition/open-access"), opdsEnclosure(reverse("opds_catalog:download", kwargs={"book_id":item.id,"zip_flag":1}),"application/fb2+zip", "http://opds-spec.org/acquisition/open-access"), opdsEnclosure(reverse("opds_catalog:cover", kwargs={"book_id":item.id}),"image/jpeg", "http://opds-spec.org/image"), opdsEnclosure(reverse("opds_catalog:download", kwargs={"book_id":item['id'],"zip_flag":0}),"application/fb2" ,"http://opds-spec.org/acquisition/open-access"), opdsEnclosure(reverse("opds_catalog:download", kwargs={"book_id":item['id'],"zip_flag":1}),"application/fb2+zip", "http://opds-spec.org/acquisition/open-access"), opdsEnclosure(reverse("opds_catalog:cover", kwargs={"book_id":item['id']}),"image/jpeg", "http://opds-spec.org/image"), ) def item_description(self, item): if item['is_catalog']: return item['title'] else: s="<b> Book name: </b>%(title)s<br/>" if item['authors']: s += "<b>Authors: </b>%(authors)s<br/>" if item['genres']: s += "<b>Genres: </b>%(genres)s<br/>" if item['series']: s += "<b>Series: </b>%(series)s<br/>" s += "<b>File: </b>%(filename)s<br/><b>File size: </b>%(filesize)s<br/><b>Changes date: </b>%(docdate)s<br/>" #if item['doubles']: s += "<b>Doubles count: </b>%(doubles)s<br/>" s +="<p class='book'>%(annotation)s</p>" print(item['authors']) return s%{'title':item['title'],'filename':item['filename'], 'filesize':item['filesize'],'docdate':item['docdate'],'annotation':item['annotation'], 'authors':", ".join(a['full_name'] for a in item['authors']), 'genres':", ".join(g['subsection'] for g in item['genres']), 'series':", ".join(s['ser'] for s in item['series']), } def OpenSearch(request): """ Выводим шаблон поиска Loading opds_catalog/sviews.py 0 → 100644 +262 −0 Original line number Diff line number Diff line from __future__ import unicode_literals from calendar import timegm from django.conf import settings from django.contrib.sites.shortcuts import get_current_site from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist from django.http import Http404, HttpResponse from django.template import TemplateDoesNotExist, loader from django.utils import feedgenerator, six from django.utils.encoding import force_text, iri_to_uri, smart_text from django.utils.html import escape from django.utils.http import http_date from django.utils.timezone import get_default_timezone, is_naive, make_aware import time def add_domain(domain, url, secure=False): protocol = 'https' if secure else 'http' if url.startswith('//'): # Support network-path reference (see #16753) - RSS requires a protocol url = '%s:%s' % (protocol, url) elif not url.startswith(('http://', 'https://', 'mailto:')): url = iri_to_uri('%s://%s%s' % (protocol, domain, url)) return url class FeedDoesNotExist(ObjectDoesNotExist): pass class Feed(object): feed_type = feedgenerator.DefaultFeed title_template = None description_template = None def __call__(self, request, *args, **kwargs): print('__call__ 1', time.time()) try: obj = self.get_object(request, *args, **kwargs) except ObjectDoesNotExist: raise Http404('Feed object does not exist.') print('__call__ 2', time.time()) feedgen = self.get_feed(obj, request) print('__call__ 3', time.time()) response = HttpResponse(content_type=feedgen.content_type) print('__call__ 4', time.time()) if hasattr(self, 'item_pubdate') or hasattr(self, 'item_updateddate'): # if item_pubdate or item_updateddate is defined for the feed, set # header so as ConditionalGetMiddleware is able to send 304 NOT MODIFIED response['Last-Modified'] = http_date( timegm(feedgen.latest_post_date().utctimetuple())) print('__call__ 6', time.time()) feedgen.write(response, 'utf-8') print('__call__ 7', time.time()) return response def item_title(self, item): # Titles should be double escaped by default (see #6533) return escape(force_text(item)) def item_description(self, item): return force_text(item) def item_link(self, item): try: return item.get_absolute_url() except AttributeError: raise ImproperlyConfigured( 'Give your %s class a get_absolute_url() method, or define an ' 'item_link() method in your Feed class.' % item.__class__.__name__ ) def item_enclosures(self, item): enc_url = self.__get_dynamic_attr('item_enclosure_url', item) if enc_url: enc = feedgenerator.Enclosure( url=smart_text(enc_url), length=smart_text(self.__get_dynamic_attr('item_enclosure_length', item)), mime_type=smart_text(self.__get_dynamic_attr('item_enclosure_mime_type', item)), ) return [enc] return [] def __get_dynamic_attr(self, attname, obj, default=None): try: attr = getattr(self, attname) except AttributeError: return default if callable(attr): # Check co_argcount rather than try/excepting the function and # catching the TypeError, because something inside the function # may raise the TypeError. This technique is more accurate. try: code = six.get_function_code(attr) except AttributeError: code = six.get_function_code(attr.__call__) if code.co_argcount == 2: # one argument is 'self' return attr(obj) else: return attr() return attr def feed_extra_kwargs(self, obj): """ Returns an extra keyword arguments dictionary that is used when initializing the feed generator. """ return {} def item_extra_kwargs(self, item): """ Returns an extra keyword arguments dictionary that is used with the `add_item` call of the feed generator. """ return {} def get_object(self, request, *args, **kwargs): return None def get_context_data(self, **kwargs): """ Returns a dictionary to use as extra context if either ``self.description_template`` or ``self.item_template`` are used. Default implementation preserves the old behavior of using {'obj': item, 'site': current_site} as the context. """ return {'obj': kwargs.get('item'), 'site': kwargs.get('site')} def get_feed(self, obj, request): """ Returns a feedgenerator.DefaultFeed object, fully populated, for this feed. Raises FeedDoesNotExist for invalid parameters. """ print('get_feed 1', time.time()) current_site = get_current_site(request) print('get_feed 2', time.time()) link = self.__get_dynamic_attr('link', obj) print('get_feed 3', time.time()) link = add_domain(current_site.domain, link, request.is_secure()) print('get_feed 4', time.time()) feed = self.feed_type( title=self.__get_dynamic_attr('title', obj), subtitle=self.__get_dynamic_attr('subtitle', obj), link=link, description=self.__get_dynamic_attr('description', obj), language=settings.LANGUAGE_CODE, feed_url=add_domain( current_site.domain, self.__get_dynamic_attr('feed_url', obj) or request.path, request.is_secure(), ), author_name=self.__get_dynamic_attr('author_name', obj), author_link=self.__get_dynamic_attr('author_link', obj), author_email=self.__get_dynamic_attr('author_email', obj), categories=self.__get_dynamic_attr('categories', obj), feed_copyright=self.__get_dynamic_attr('feed_copyright', obj), feed_guid=self.__get_dynamic_attr('feed_guid', obj), ttl=self.__get_dynamic_attr('ttl', obj), **self.feed_extra_kwargs(obj) ) print('get_feed 5', time.time()) title_tmp = None if self.title_template is not None: try: title_tmp = loader.get_template(self.title_template) except TemplateDoesNotExist: pass print('get_feed 6', time.time()) description_tmp = None if self.description_template is not None: try: description_tmp = loader.get_template(self.description_template) except TemplateDoesNotExist: pass print('get_feed 7', time.time()) i=0 for item in self.__get_dynamic_attr('items', obj): if i==0: print('for item 1', time.time()) context = self.get_context_data(item=item, site=current_site, obj=obj, request=request) if i==0: print('for item 2', time.time()) if title_tmp is not None: title = title_tmp.render(context, request) else: title = self.__get_dynamic_attr('item_title', item) if i==0: print('for item 3', time.time()) if description_tmp is not None: description = description_tmp.render(context, request) else: description = self.__get_dynamic_attr('item_description', item) if i==0: print('for item 4', time.time()) link = add_domain( current_site.domain, self.__get_dynamic_attr('item_link', item), request.is_secure(), ) if i==0: print('for item 5', time.time()) enclosures = self.__get_dynamic_attr('item_enclosures', item) if i==0: print('for item 6', time.time()) author_name = self.__get_dynamic_attr('item_author_name', item) if i==0: print('for item 7', time.time()) if author_name is not None: author_email = self.__get_dynamic_attr('item_author_email', item) author_link = self.__get_dynamic_attr('item_author_link', item) else: author_email = author_link = None if i==0: print('for item 8', time.time()) tz = get_default_timezone() if i==0: print('for item 9', time.time()) pubdate = self.__get_dynamic_attr('item_pubdate', item) if i==0: print('for item 10', time.time()) if pubdate and is_naive(pubdate): pubdate = make_aware(pubdate, tz) if i==0: print('for item 11', time.time()) updateddate = self.__get_dynamic_attr('item_updateddate', item) if i==0: print('for item 12', time.time()) if updateddate and is_naive(updateddate): updateddate = make_aware(updateddate, tz) if i==0: print('for item 13', time.time()) feed.add_item( title=title, link=link, description=description, unique_id=self.__get_dynamic_attr('item_guid', item, link), unique_id_is_permalink=self.__get_dynamic_attr( 'item_guid_is_permalink', item), enclosures=enclosures, pubdate=pubdate, updateddate=updateddate, author_name=author_name, author_email=author_email, author_link=author_link, categories=self.__get_dynamic_attr('item_categories', item), item_copyright=self.__get_dynamic_attr('item_copyright', item), **self.item_extra_kwargs(item) ) if i==0: print('for item 14', time.time()) i += 1 print('get_feed 8', time.time(), i) return feed opds_catalog/templates/book_description.html +2 −2 Original line number Diff line number Diff line {% load i18n %} {% autoescape off %} {% if obj.cat_name %} {{ obj.cat_name }} {% if obj.is_catalog %} {{ obj.title }} {% else %} <b>{% trans "Book name:" %} </b>{{ obj.title }}<br/> {% if obj.authors %}<b>{% trans "Authors:" %} </b>{% for a in obj.authors %}{{ a.full_name }}; {% endfor %}<br/>{% endif %} Loading opds_catalog/templates/book_description_cat.html +4 −4 Original line number Diff line number Diff line Loading @@ -5,9 +5,9 @@ {{ obj.cat_name }} {% else %} <b>{% trans "Book name:" %} </b>{{ obj.title }}<br/> <b>{% trans "Authors:" %} </b>{% for a in obj.authors.all %}{{ a.full_name }}; {% endfor %}<br/> <b>{% trans "Genres:" %} </b>{% for g in obj.genres.all %}{{ g.subsection }}; {% endfor %}<br/> <b>{% trans "Series:" %} </b>{% for s in obj.series.all %}{{s.ser}}; {% endfor %}<br/> {% if obj.authors %}<b>{% trans "Authors:" %} </b>{% for a in obj.authors.all %}{{ a.full_name }}; {% endfor %}<br/>{% endif %} {% if obj.genres %}<b>{% trans "Genres:" %} </b>{% for g in obj.genres.all %}{{ g.subsection }}; {% endfor %}<br/>{% endif %} {% if obj.series %}<b>{% trans "Series:" %} </b>{% for s in obj.series.all %}{{s.ser}}; {% endfor %}<br/>{% endif %} <b>{% trans "File:" %} </b>{{ obj.filename }}<br/> <b>{% trans "File size:" %} </b>{{ obj.filesize }}<br/> <b>{% trans "Changes date:" %} </b>{{ obj.docdate }}<br/> Loading sopds_web_backend/views.py +13 −13 Original line number Diff line number Diff line from random import randint from itertools import chain from django.shortcuts import render, redirect from django.template.context_processors import csrf from django.core.paginator import Paginator, InvalidPage from django.db.models import Count, Min from django.utils.translation import ugettext as _ from django.contrib.auth import authenticate, login, logout, REDIRECT_FIELD_NAME from django.contrib.auth import authenticate, login, REDIRECT_FIELD_NAME from django.contrib.auth.decorators import user_passes_test from django.core.urlresolvers import reverse, reverse_lazy Loading Loading @@ -158,12 +156,13 @@ def SearchBooksView(request): elif searchtype == 'i': try: book_id = int(searchterms) btitle = Book.objects.get(id=book_id).title mbook = Book.objects.get(id=book_id) except: book_id = 0 btitle = "" books = Book.objects.filter(id=book_id) args['breadcrumbs'] = [_('Books'),btitle] mbook = None #books = Book.objects.filter(id=book_id) books = Book.objects.filter(title__iexact=mbook.title, authors__in=mbook.authors.all()).distinct().order_by('-docdate') args['breadcrumbs'] = [_('Books'),mbook.title] args['searchobject'] = 'title' # prefetch_related on sqlite on items >999 therow error "too many SQL variables" Loading Loading @@ -212,6 +211,7 @@ def SearchBooksView(request): else: double_flag = False if op.d1_first_pos!=0: items.pop(0) args['paginator'] = op.get_data_dict() Loading Loading @@ -520,13 +520,13 @@ def LoginView(request): except KeyError: return render(request, 'sopds_login.html', args) next = request.GET.get('next',reverse("web:main")) next_url = request.GET.get('next',reverse("web:main")) user = authenticate(username=username, password=password) if user is not None: if user.is_active: login(request, user) return redirect(next) return redirect(next_url) else: args['system_message']={'text':_('This account is not active!'),'type':'alert'} return render(request, 'sopds_login.html', args) Loading Loading
opds_catalog/feeds.py +82 −48 Original line number Diff line number Diff line from itertools import chain from opds_catalog.sviews import Feed #from itertools import chain from django.utils import timezone from django.utils.translation import ugettext as _ from django.utils.feedgenerator import Atom1Feed, Enclosure, rfc3339_date from django.contrib.syndication.views import Feed #from django.contrib.syndication.views import Feed from django.core.urlresolvers import reverse from django.core.paginator import Paginator, EmptyPage from django.shortcuts import render from django.db.models import Count, Min, Sum from django.db.models import Count, Min from opds_catalog.models import Book, Catalog, Author, Genre, Series, bookshelf, Counter, lang_menu from opds_catalog import models from opds_catalog import settings from opds_catalog.opds_middleware import BasicAuthMiddleware from opds_catalog.opds_paginator import Paginator as OPDS_Paginator import time class AuthFeed(Feed): request = None Loading Loading @@ -197,38 +201,66 @@ class MainFeed(AuthFeed): class CatalogsFeed(AuthFeed): feed_type = opdsFeed subtitle = settings.SUBTITLE description_template = "book_description_cat.html" ##description_template = "book_description.html" def get_object(self, request, cat_id=None, page=1): print('get_object', time.time()) if not isinstance(page, int): page = int(page) try: if cat_id is not None: return (Catalog.objects.get(id=cat_id), page) cat = Catalog.objects.get(id=cat_id) else: return (Catalog.objects.get(parent__id=cat_id), page) cat = Catalog.objects.get(parent__id=cat_id) except Catalog.DoesNotExist: cat = None catalogs_list = Catalog.objects.filter(parent=cat).order_by("cat_name") catalogs_count = catalogs_list.count() # prefetch_related on sqlite on items >999 therow error "too many SQL variables" #books_list = Book.objects.filter(catalog=cat).prefetch_related('authors','genres','series').order_by("title") books_list = Book.objects.filter(catalog=cat).order_by("search_title") books_count = books_list.count() # Получаем результирующий список op = OPDS_Paginator(catalogs_count, books_count, page, settings.MAXITEMS) items = [] for row in catalogs_list[op.d1_first_pos:op.d1_last_pos]: p = {'is_catalog':1, 'title': row.cat_name,'id': row.id, 'cat_type':row.cat_type, 'parent_id':row.parent_id} items.append(p) for row in books_list[op.d2_first_pos:op.d2_last_pos]: p = {'is_catalog':0, 'lang_code': row.lang_code, 'filename': row.filename, 'path': row.path, \ 'registerdate': row.registerdate, 'id': row.id, 'annotation': row.annotation, \ 'docdate': row.docdate, 'format': row.format, 'title': row.title, 'filesize': row.filesize//1000, 'authors':row.authors.values(), 'genres':row.genres.values(), 'series':row.series.values()} items.append(p) return items, cat, op.get_data_dict() def title(self, obj): cat, current_page = obj items, cat, paginator = obj if cat.parent: return "%s | %s | %s"%(settings.TITLE,_("By catalogs"), cat.path) else: return "%s | %s"%(settings.TITLE,_("By catalogs")) def link(self, obj): cat, current_page = obj return reverse("opds_catalog:cat_page", kwargs={"cat_id":cat.id, "page":current_page}) items, cat, paginator = obj return reverse("opds_catalog:cat_page", kwargs={"cat_id":cat.id, "page":paginator['number']}) def feed_extra_kwargs(self, obj): cat, current_page = obj items, cat, paginator = obj start_url = reverse("opds_catalog:main") if current_page != 1: prev_url = reverse("opds_catalog:cat_page", kwargs={"cat_id":cat.id,"page":(current_page-1)}) if paginator['has_previos']: prev_url = reverse("opds_catalog:cat_page", kwargs={"cat_id":cat.id,"page":paginator['previous_page_number']}) else: prev_url = None if current_page*settings.MAXITEMS<Catalog.objects.filter(parent=cat).count() + Book.objects.filter(catalog=cat).count(): next_url = reverse("opds_catalog:cat_page", kwargs={"cat_id":cat.id,"page":(current_page+1)}) if paginator['has_next']: next_url = reverse("opds_catalog:cat_page", kwargs={"cat_id":cat.id,"page":paginator['next_page_number']}) else: next_url = None Loading @@ -240,49 +272,51 @@ class CatalogsFeed(AuthFeed): } def items(self, obj): cat, current_page = obj catalogs_list = Catalog.objects.filter(parent=cat).order_by("cat_name") # prefetch_related on sqlite on items >999 therow error "too many SQL variables" #books_list = Book.objects.filter(catalog=cat).prefetch_related('authors','genres','series').order_by("title") books_list = Book.objects.filter(catalog=cat).order_by("search_title") union_list = list(chain(catalogs_list,books_list)) paginator = Paginator(union_list,settings.MAXITEMS) try: page = paginator.page(current_page) except EmptyPage: page = paginator.page(paginator.num_pages) return page items, cat, paginator = obj print('items', time.time()) return items def item_title(self, item): if isinstance(item, Catalog): return item.cat_name else: return item.title return item['title'] def item_guid(self, item): if isinstance(item, Catalog): gp = 'c:' else: gp = 'b:' return "%s%s"%(gp,item.id) gp = 'c:' if item['is_catalog'] else 'b:' return "%s%s"%(gp,item['id']) def item_link(self, item): if isinstance(item, Catalog): return reverse("opds_catalog:cat_tree", kwargs={"cat_id":item.id}) if item['is_catalog']: return reverse("opds_catalog:cat_tree", kwargs={"cat_id":item['id']}) else: return reverse("opds_catalog:download", kwargs={"book_id":item.id,"zip_flag":0}) return reverse("opds_catalog:download", kwargs={"book_id":item['id'],"zip_flag":0}) def item_enclosures(self, item): if isinstance(item, Catalog): return (opdsEnclosure(reverse("opds_catalog:cat_tree", kwargs={"cat_id":item.id}),"application/atom+xml;profile=opds-catalog;kind=navigation", "subsection"),) if item['is_catalog']: return (opdsEnclosure(reverse("opds_catalog:cat_tree", kwargs={"cat_id":item['id']}),"application/atom+xml;profile=opds-catalog;kind=navigation", "subsection"),) else: return ( opdsEnclosure(reverse("opds_catalog:download", kwargs={"book_id":item.id,"zip_flag":0}),"application/fb2" ,"http://opds-spec.org/acquisition/open-access"), opdsEnclosure(reverse("opds_catalog:download", kwargs={"book_id":item.id,"zip_flag":1}),"application/fb2+zip", "http://opds-spec.org/acquisition/open-access"), opdsEnclosure(reverse("opds_catalog:cover", kwargs={"book_id":item.id}),"image/jpeg", "http://opds-spec.org/image"), opdsEnclosure(reverse("opds_catalog:download", kwargs={"book_id":item['id'],"zip_flag":0}),"application/fb2" ,"http://opds-spec.org/acquisition/open-access"), opdsEnclosure(reverse("opds_catalog:download", kwargs={"book_id":item['id'],"zip_flag":1}),"application/fb2+zip", "http://opds-spec.org/acquisition/open-access"), opdsEnclosure(reverse("opds_catalog:cover", kwargs={"book_id":item['id']}),"image/jpeg", "http://opds-spec.org/image"), ) def item_description(self, item): if item['is_catalog']: return item['title'] else: s="<b> Book name: </b>%(title)s<br/>" if item['authors']: s += "<b>Authors: </b>%(authors)s<br/>" if item['genres']: s += "<b>Genres: </b>%(genres)s<br/>" if item['series']: s += "<b>Series: </b>%(series)s<br/>" s += "<b>File: </b>%(filename)s<br/><b>File size: </b>%(filesize)s<br/><b>Changes date: </b>%(docdate)s<br/>" #if item['doubles']: s += "<b>Doubles count: </b>%(doubles)s<br/>" s +="<p class='book'>%(annotation)s</p>" print(item['authors']) return s%{'title':item['title'],'filename':item['filename'], 'filesize':item['filesize'],'docdate':item['docdate'],'annotation':item['annotation'], 'authors':", ".join(a['full_name'] for a in item['authors']), 'genres':", ".join(g['subsection'] for g in item['genres']), 'series':", ".join(s['ser'] for s in item['series']), } def OpenSearch(request): """ Выводим шаблон поиска Loading
opds_catalog/sviews.py 0 → 100644 +262 −0 Original line number Diff line number Diff line from __future__ import unicode_literals from calendar import timegm from django.conf import settings from django.contrib.sites.shortcuts import get_current_site from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist from django.http import Http404, HttpResponse from django.template import TemplateDoesNotExist, loader from django.utils import feedgenerator, six from django.utils.encoding import force_text, iri_to_uri, smart_text from django.utils.html import escape from django.utils.http import http_date from django.utils.timezone import get_default_timezone, is_naive, make_aware import time def add_domain(domain, url, secure=False): protocol = 'https' if secure else 'http' if url.startswith('//'): # Support network-path reference (see #16753) - RSS requires a protocol url = '%s:%s' % (protocol, url) elif not url.startswith(('http://', 'https://', 'mailto:')): url = iri_to_uri('%s://%s%s' % (protocol, domain, url)) return url class FeedDoesNotExist(ObjectDoesNotExist): pass class Feed(object): feed_type = feedgenerator.DefaultFeed title_template = None description_template = None def __call__(self, request, *args, **kwargs): print('__call__ 1', time.time()) try: obj = self.get_object(request, *args, **kwargs) except ObjectDoesNotExist: raise Http404('Feed object does not exist.') print('__call__ 2', time.time()) feedgen = self.get_feed(obj, request) print('__call__ 3', time.time()) response = HttpResponse(content_type=feedgen.content_type) print('__call__ 4', time.time()) if hasattr(self, 'item_pubdate') or hasattr(self, 'item_updateddate'): # if item_pubdate or item_updateddate is defined for the feed, set # header so as ConditionalGetMiddleware is able to send 304 NOT MODIFIED response['Last-Modified'] = http_date( timegm(feedgen.latest_post_date().utctimetuple())) print('__call__ 6', time.time()) feedgen.write(response, 'utf-8') print('__call__ 7', time.time()) return response def item_title(self, item): # Titles should be double escaped by default (see #6533) return escape(force_text(item)) def item_description(self, item): return force_text(item) def item_link(self, item): try: return item.get_absolute_url() except AttributeError: raise ImproperlyConfigured( 'Give your %s class a get_absolute_url() method, or define an ' 'item_link() method in your Feed class.' % item.__class__.__name__ ) def item_enclosures(self, item): enc_url = self.__get_dynamic_attr('item_enclosure_url', item) if enc_url: enc = feedgenerator.Enclosure( url=smart_text(enc_url), length=smart_text(self.__get_dynamic_attr('item_enclosure_length', item)), mime_type=smart_text(self.__get_dynamic_attr('item_enclosure_mime_type', item)), ) return [enc] return [] def __get_dynamic_attr(self, attname, obj, default=None): try: attr = getattr(self, attname) except AttributeError: return default if callable(attr): # Check co_argcount rather than try/excepting the function and # catching the TypeError, because something inside the function # may raise the TypeError. This technique is more accurate. try: code = six.get_function_code(attr) except AttributeError: code = six.get_function_code(attr.__call__) if code.co_argcount == 2: # one argument is 'self' return attr(obj) else: return attr() return attr def feed_extra_kwargs(self, obj): """ Returns an extra keyword arguments dictionary that is used when initializing the feed generator. """ return {} def item_extra_kwargs(self, item): """ Returns an extra keyword arguments dictionary that is used with the `add_item` call of the feed generator. """ return {} def get_object(self, request, *args, **kwargs): return None def get_context_data(self, **kwargs): """ Returns a dictionary to use as extra context if either ``self.description_template`` or ``self.item_template`` are used. Default implementation preserves the old behavior of using {'obj': item, 'site': current_site} as the context. """ return {'obj': kwargs.get('item'), 'site': kwargs.get('site')} def get_feed(self, obj, request): """ Returns a feedgenerator.DefaultFeed object, fully populated, for this feed. Raises FeedDoesNotExist for invalid parameters. """ print('get_feed 1', time.time()) current_site = get_current_site(request) print('get_feed 2', time.time()) link = self.__get_dynamic_attr('link', obj) print('get_feed 3', time.time()) link = add_domain(current_site.domain, link, request.is_secure()) print('get_feed 4', time.time()) feed = self.feed_type( title=self.__get_dynamic_attr('title', obj), subtitle=self.__get_dynamic_attr('subtitle', obj), link=link, description=self.__get_dynamic_attr('description', obj), language=settings.LANGUAGE_CODE, feed_url=add_domain( current_site.domain, self.__get_dynamic_attr('feed_url', obj) or request.path, request.is_secure(), ), author_name=self.__get_dynamic_attr('author_name', obj), author_link=self.__get_dynamic_attr('author_link', obj), author_email=self.__get_dynamic_attr('author_email', obj), categories=self.__get_dynamic_attr('categories', obj), feed_copyright=self.__get_dynamic_attr('feed_copyright', obj), feed_guid=self.__get_dynamic_attr('feed_guid', obj), ttl=self.__get_dynamic_attr('ttl', obj), **self.feed_extra_kwargs(obj) ) print('get_feed 5', time.time()) title_tmp = None if self.title_template is not None: try: title_tmp = loader.get_template(self.title_template) except TemplateDoesNotExist: pass print('get_feed 6', time.time()) description_tmp = None if self.description_template is not None: try: description_tmp = loader.get_template(self.description_template) except TemplateDoesNotExist: pass print('get_feed 7', time.time()) i=0 for item in self.__get_dynamic_attr('items', obj): if i==0: print('for item 1', time.time()) context = self.get_context_data(item=item, site=current_site, obj=obj, request=request) if i==0: print('for item 2', time.time()) if title_tmp is not None: title = title_tmp.render(context, request) else: title = self.__get_dynamic_attr('item_title', item) if i==0: print('for item 3', time.time()) if description_tmp is not None: description = description_tmp.render(context, request) else: description = self.__get_dynamic_attr('item_description', item) if i==0: print('for item 4', time.time()) link = add_domain( current_site.domain, self.__get_dynamic_attr('item_link', item), request.is_secure(), ) if i==0: print('for item 5', time.time()) enclosures = self.__get_dynamic_attr('item_enclosures', item) if i==0: print('for item 6', time.time()) author_name = self.__get_dynamic_attr('item_author_name', item) if i==0: print('for item 7', time.time()) if author_name is not None: author_email = self.__get_dynamic_attr('item_author_email', item) author_link = self.__get_dynamic_attr('item_author_link', item) else: author_email = author_link = None if i==0: print('for item 8', time.time()) tz = get_default_timezone() if i==0: print('for item 9', time.time()) pubdate = self.__get_dynamic_attr('item_pubdate', item) if i==0: print('for item 10', time.time()) if pubdate and is_naive(pubdate): pubdate = make_aware(pubdate, tz) if i==0: print('for item 11', time.time()) updateddate = self.__get_dynamic_attr('item_updateddate', item) if i==0: print('for item 12', time.time()) if updateddate and is_naive(updateddate): updateddate = make_aware(updateddate, tz) if i==0: print('for item 13', time.time()) feed.add_item( title=title, link=link, description=description, unique_id=self.__get_dynamic_attr('item_guid', item, link), unique_id_is_permalink=self.__get_dynamic_attr( 'item_guid_is_permalink', item), enclosures=enclosures, pubdate=pubdate, updateddate=updateddate, author_name=author_name, author_email=author_email, author_link=author_link, categories=self.__get_dynamic_attr('item_categories', item), item_copyright=self.__get_dynamic_attr('item_copyright', item), **self.item_extra_kwargs(item) ) if i==0: print('for item 14', time.time()) i += 1 print('get_feed 8', time.time(), i) return feed
opds_catalog/templates/book_description.html +2 −2 Original line number Diff line number Diff line {% load i18n %} {% autoescape off %} {% if obj.cat_name %} {{ obj.cat_name }} {% if obj.is_catalog %} {{ obj.title }} {% else %} <b>{% trans "Book name:" %} </b>{{ obj.title }}<br/> {% if obj.authors %}<b>{% trans "Authors:" %} </b>{% for a in obj.authors %}{{ a.full_name }}; {% endfor %}<br/>{% endif %} Loading
opds_catalog/templates/book_description_cat.html +4 −4 Original line number Diff line number Diff line Loading @@ -5,9 +5,9 @@ {{ obj.cat_name }} {% else %} <b>{% trans "Book name:" %} </b>{{ obj.title }}<br/> <b>{% trans "Authors:" %} </b>{% for a in obj.authors.all %}{{ a.full_name }}; {% endfor %}<br/> <b>{% trans "Genres:" %} </b>{% for g in obj.genres.all %}{{ g.subsection }}; {% endfor %}<br/> <b>{% trans "Series:" %} </b>{% for s in obj.series.all %}{{s.ser}}; {% endfor %}<br/> {% if obj.authors %}<b>{% trans "Authors:" %} </b>{% for a in obj.authors.all %}{{ a.full_name }}; {% endfor %}<br/>{% endif %} {% if obj.genres %}<b>{% trans "Genres:" %} </b>{% for g in obj.genres.all %}{{ g.subsection }}; {% endfor %}<br/>{% endif %} {% if obj.series %}<b>{% trans "Series:" %} </b>{% for s in obj.series.all %}{{s.ser}}; {% endfor %}<br/>{% endif %} <b>{% trans "File:" %} </b>{{ obj.filename }}<br/> <b>{% trans "File size:" %} </b>{{ obj.filesize }}<br/> <b>{% trans "Changes date:" %} </b>{{ obj.docdate }}<br/> Loading
sopds_web_backend/views.py +13 −13 Original line number Diff line number Diff line from random import randint from itertools import chain from django.shortcuts import render, redirect from django.template.context_processors import csrf from django.core.paginator import Paginator, InvalidPage from django.db.models import Count, Min from django.utils.translation import ugettext as _ from django.contrib.auth import authenticate, login, logout, REDIRECT_FIELD_NAME from django.contrib.auth import authenticate, login, REDIRECT_FIELD_NAME from django.contrib.auth.decorators import user_passes_test from django.core.urlresolvers import reverse, reverse_lazy Loading Loading @@ -158,12 +156,13 @@ def SearchBooksView(request): elif searchtype == 'i': try: book_id = int(searchterms) btitle = Book.objects.get(id=book_id).title mbook = Book.objects.get(id=book_id) except: book_id = 0 btitle = "" books = Book.objects.filter(id=book_id) args['breadcrumbs'] = [_('Books'),btitle] mbook = None #books = Book.objects.filter(id=book_id) books = Book.objects.filter(title__iexact=mbook.title, authors__in=mbook.authors.all()).distinct().order_by('-docdate') args['breadcrumbs'] = [_('Books'),mbook.title] args['searchobject'] = 'title' # prefetch_related on sqlite on items >999 therow error "too many SQL variables" Loading Loading @@ -212,6 +211,7 @@ def SearchBooksView(request): else: double_flag = False if op.d1_first_pos!=0: items.pop(0) args['paginator'] = op.get_data_dict() Loading Loading @@ -520,13 +520,13 @@ def LoginView(request): except KeyError: return render(request, 'sopds_login.html', args) next = request.GET.get('next',reverse("web:main")) next_url = request.GET.get('next',reverse("web:main")) user = authenticate(username=username, password=password) if user is not None: if user.is_active: login(request, user) return redirect(next) return redirect(next_url) else: args['system_message']={'text':_('This account is not active!'),'type':'alert'} return render(request, 'sopds_login.html', args) Loading