class ProductVersionView(ListView): template_name = 'security/product-advisories.html' context_object_name = 'product_versions' allow_empty = False @method_decorator(cache_control_expires(0.5)) @method_decorator(last_modified(latest_advisory)) def dispatch(self, request, *args, **kwargs): return super(ProductVersionView, self).dispatch(request, *args, **kwargs) def get_queryset(self): slug = u'{product}-{version}'.format(**self.kwargs) qfilter = Q(slug__startswith=slug + '.') dots = slug.count('.') if dots < 2: # add exact match if not point release if slug.endswith('.0'): # stip trailing .0 as products are stored without them slug = slug[:-2] qfilter |= Q(slug__exact=slug) versions = Product.objects.filter(qfilter) return sorted(versions, reverse=True) def get_context_data(self, **kwargs): cxt = super(ProductVersionView, self).get_context_data(**kwargs) prod_name, version = self.kwargs['product'], self.kwargs['version'] cxt['is_obsolete'] = product_is_obsolete(prod_name, version) cxt['product_name'] = '{0} {1}'.format(cxt['product_versions'][0].product, version) cxt['product_slug'] = prod_name return cxt
class VolumePageList(ListView, VaryOnCookieMixin): '''Display a paginated list of :class:`~readux.books.models.Page` objects associated with a single :class:`~readux.books.models.Volume`. Pages are displayed by thumbnail; thumbnails include an annotation count indicator for logged in users with annotations. ''' template_name = 'books/volume_pages_list.html' paginate_by = 30 context_object_name = 'pages' @method_decorator(last_modified(view_helpers.volume_pages_modified)) def dispatch(self, *args, **kwargs): return super(VolumePageList, self).dispatch(*args, **kwargs) def get_queryset(self): self.repo = Repository(request=self.request) # store the volume for use in get_context_data self.vol = self.repo.get_object(self.kwargs['pid'], type=Volume) if not self.vol.exists or not self.vol.is_a_volume: raise Http404 return self.vol.find_solr_pages() def get_context_data(self, **kwargs): context_data = super(VolumePageList, self).get_context_data() context_data.update({ 'vol': self.vol, 'form': BookSearch(), # form for searching in this book }) # if user is authenticated, check for annotations on this volume if self.request.user.is_authenticated(): notes = self.vol.page_annotation_count(self.request.user) # method returns a dict for easy lookup; # strip out base site url for easy lookup in the template # (need leading / left to match item urls) domain = get_current_site(self.request).domain.rstrip('/') if not domain.startswith('https'): domain = 'https://' + domain annotated_pages = dict([(k.replace(domain, ''), v) for k, v in notes.iteritems()]) else: annotated_pages = {} context_data.update({ 'annotated_pages': annotated_pages, 'annotation_search_enabled': bool(annotated_pages) }) # Check if the first page of the volume is wider than it is tall # to set the layout of the pages first_page = self.vol.pages[0] if first_page.width > first_page.height: layout = 'landscape' else: layout = 'default' context_data['layout'] = layout return context_data
class ProductView(ListView): template_name = 'security/product-advisories.html' context_object_name = 'product_versions' allow_empty = False minimum_versions = { 'firefox': Version('4.0'), 'thunderbird': Version('6.0'), 'seamonkey': Version('2.3'), } @method_decorator(cache_control_expires(0.5)) @method_decorator(last_modified(latest_advisory)) def dispatch(self, request, *args, **kwargs): return super(ProductView, self).dispatch(request, *args, **kwargs) def get_queryset(self): product_slug = self.kwargs.get('slug') versions = Product.objects.filter(product_slug=product_slug) min_version = self.minimum_versions.get(product_slug) if min_version: versions = [vers for vers in versions if vers.version >= min_version] return sorted(versions, reverse=True) def get_context_data(self, **kwargs): cxt = super(ProductView, self).get_context_data(**kwargs) cxt['product_name'] = cxt['product_versions'][0].product return cxt
class AdvisoriesView(ListView): template_name = 'security/advisories.html' queryset = SecurityAdvisory.objects.only('id', 'impact', 'title', 'announced') context_object_name = 'advisories' @method_decorator(cache_control_expires(0.5)) @method_decorator(last_modified(latest_advisory)) def dispatch(self, request, *args, **kwargs): return super(AdvisoriesView, self).dispatch(request, *args, **kwargs)
class AdvisoryView(DetailView): model = SecurityAdvisory template_name = 'security/advisory.html' context_object_name = 'advisory' @method_decorator(cache_control_expires(0.5)) @method_decorator(last_modified(latest_advisory)) def dispatch(self, request, *args, **kwargs): return super(AdvisoryView, self).dispatch(request, *args, **kwargs)
def as_view(cls, **initkwargs): def normalize_key_prefix(key_prefix): def _key_prefix(request, *args, **kwargs): return str( key_prefix(request, *args, **kwargs) ).replace(' ', '_') return _key_prefix patched_view = view = super().as_view(**initkwargs) patched_view = http.etag(cls.etag)(patched_view) patched_view = http.last_modified(cls.last_modified)(patched_view) patched_view = cache_page( cache_timeout=cls._expires, key_prefix=normalize_key_prefix(cls.last_modified), )(patched_view) view = decorators.replace_if( lambda request, *args, **kwargs: request.method in ('GET', 'HEAD'), replacement=patched_view, )(view) @functools.wraps(cls.as_view) def logging_view(request, *args, **kwargs): request_logger.debug( 'request_method: %(request_method)s, ' 'request_path: %(request_path)s, ' 'request_headers: %(request_headers)s, ' 'request_params: %(request_params)s, ' 'request_data: %(request_data)s, ', dict( request_method=request.method, request_path=request.path, request_headers=request.META, request_params=request.GET, request_data=request.POST, ), ) response = view(request, *args, **kwargs) response_logger.debug( 'response_code: %(response_code)s, ' 'response_headers: %(response_headers)s, ' 'response_data: %(response_data)s', dict( response_code=response.status_code, response_headers=response.items(), response_data=response.content, ), ) return response return logging_view
class CollectionList(ListView): '''List and display all collections''' model = Collection template_name = 'collection/collection_list.html' display_mode = 'list' @method_decorator(last_modified(view_helpers.collections_modified)) def dispatch(self, *args, **kwargs): return super(CollectionList, self).dispatch(*args, **kwargs) def get_queryset(self): solr = solr_interface() solrq = solr.query(content_model=Collection.COLLECTION_CONTENT_MODEL) \ .sort_by('title_exact') \ .results_as(SolrCollection) # optional collection owner in settings; if set, filter collections # by the specified owner collection_owner = getattr(settings, 'COLLECTIONS_OWNER', None) if collection_owner: solrq = solrq.filter(owner=collection_owner) return solrq def get_context_data(self, **kwargs): solr = solr_interface() q = solr.query(content_model=Volume.VOLUME_CMODEL_PATTERN) \ .facet_by('collection_id', sort='count', mincount=1) \ .paginate(rows=0) facets = q.execute().facet_counts.facet_fields # convert into dictionary for access by pid collection_counts = dict([(pid, total) for pid, total in facets['collection_id']]) # generate a list of tuple of solr result, volume count, # filtering out any collections with no items collections = [(r, collection_counts.get(r['pid'])) for r in self.object_list if r['pid'] in collection_counts] # generate a random list of 4 covers for use in twitter gallery card # - restrict to collections with cover images covers = [coll.cover for coll, count in collections if coll.cover] # - randomize the list in place so we can grab the first N shuffle(covers) return { 'collections': collections, 'mode': self.display_mode, 'meta_covers': covers[:4] }
def list(self, request): def get_last_modified(request): try: latest_wortwurst = self.filter_qs.latest('created').created except Wortwurst.DoesNotExist: latest_wortwurst = epoch try: latest_vote = Vote.objects.latest('created').created except Vote.DoesNotExist: latest_vote = epoch return max(latest_wortwurst, latest_vote) return last_modified(get_last_modified)( super(WortwurstViewSet, self).list )(request)
def index(self, request, pk=None): def get_last_modified(request): return timezone.make_aware( datetime.datetime.utcfromtimestamp(os.stat(__file__).st_mtime) ) return last_modified(get_last_modified)( lambda request: render(request, 'wortwurster/main/index.html', { 'title': "Wortwurster", 'filters': get_filters(self.filter, self.vote_types), 'sortings': get_sortings(self.sorting), 'vote_types': self.vote_types, 'random_texts': get_random_lines(20, 480), 'id': pk, }) )(request)
def retrieve(self, request, pk): def get_last_modified(request, pk): wortwurst = self.get_object() try: latest_wortwurst = wortwurst.created except Wortwurst.DoesNotExist: latest_wortwurst = epoch try: latest_vote = wortwurst.vote_set.latest('created').created except Vote.DoesNotExist: latest_vote = epoch return max(latest_wortwurst, latest_vote) return last_modified(get_last_modified)( super(WortwurstViewSet, self).retrieve )(request, pk)
def as_view(cls, **kws): V = super(LastMod, cls).as_view(**kws) if 'time_sk' in kws: collection_name = kws['collection_name'] sk = kws['time_sk'] vk = kws.get('time_vk') or sk def _modtime(req, *args, **kws): coll = req.mongodb[collection_name] O = coll.find_one(None, fields={vk:1}, sort=[(sk,-1)]) if not O: return None else: return O[vk] V = last_modified(_modtime)(V) return never_cache(V)
def as_view(cls, **initkwargs): view = patched_view = super().as_view(**initkwargs) last_modified_evaluator = functools.lru_cache()(cls.last_modified) patched_view = last_modified(last_modified_evaluator)(patched_view) patched_view = cache_control(**cls.cache_control())(patched_view) patched_view = cache_page( None, key_prefix=last_modified_evaluator # will be used value of Cache-Control.max-age or default one )(patched_view) view = conditional(cls.cache_headers_allowed, patched_view)(view) @functools.wraps(cls.as_view) def logging_view(request, *args, **kwargs): request_logger.debug( "request_method: %(request_method)s, " "request_path: %(request_path)s, " "request_headers: %(request_headers)s, " "request_params: %(request_params)s, " "request_data: %(request_data)s, ", dict( request_method=request.method, request_path=request.path, request_headers=request.META, request_params=request.GET, request_data=request.POST, ), ) response = view(request, *args, **kwargs) response_logger.debug( "response_code: %(response_code)s, " "response_headers: %(response_headers)s, " "response_data: %(response_data)s", dict( response_code=response.status_code, response_headers=response.items(), response_data=response.content, ), ) return response return logging_view
def as_view(cls, **initkwargs): view = patched_view = super().as_view(**initkwargs) last_modified_evaluator = functools.lru_cache()(cls.last_modified) patched_view = last_modified(last_modified_evaluator)(patched_view) patched_view = cache_page( lazy(cls.expires, int)(), key_prefix=last_modified_evaluator, )(patched_view) view = conditional(cls.cache_headers_allowed, patched_view)(view) @functools.wraps(cls.as_view) def logging_view(request, *args, **kwargs): request_logger.debug( 'request_method: %(request_method)s, ' 'request_path: %(request_path)s, ' 'request_headers: %(request_headers)s, ' 'request_params: %(request_params)s, ' 'request_data: %(request_data)s, ', dict( request_method=request.method, request_path=request.path, request_headers=request.META, request_params=request.GET, request_data=request.POST, ), ) response = view(request, *args, **kwargs) response_logger.debug( 'response_code: %(response_code)s, ' 'response_headers: %(response_headers)s, ' 'response_data: %(response_data)s', dict( response_code=response.status_code, response_headers=response.items(), response_data=response.content, ), ) return response return logging_view
class ProductVersionView(ListView): template_name = 'security/product-advisories.html' context_object_name = 'product_versions' allow_empty = False @method_decorator(cache_control_expires(0.5)) @method_decorator(last_modified(latest_advisory)) def dispatch(self, request, *args, **kwargs): return super(ProductVersionView, self).dispatch(request, *args, **kwargs) def get_queryset(self): slug = self.kwargs['slug'] qfilter = Q(slug__startswith=slug + '.') dots = slug.count('.') if dots == 1: # minor version. add exact match. qfilter |= Q(slug__exact=slug) versions = Product.objects.filter(qfilter) return sorted(versions, reverse=True)
class ProductVersionView(ListView): template_name = 'security/product-advisories.html' context_object_name = 'product_versions' allow_empty = False @method_decorator(cache_control_expires(0.5)) @method_decorator(last_modified(latest_advisory)) def dispatch(self, request, *args, **kwargs): return super(ProductVersionView, self).dispatch(request, *args, **kwargs) def get_queryset(self): slug = self.kwargs['slug'] qfilter = Q(slug__startswith=slug + '.') dots = slug.count('.') if dots < 2: # add exact match if not point release if slug.endswith('.0'): # stip trailing .0 as products are stored without them slug = slug[:-2] qfilter |= Q(slug__exact=slug) versions = Product.objects.filter(qfilter) return sorted(versions, reverse=True)
'error': reason, } break if not ret: ret = { 'error': ugettext( "All IOTD slots for the next %(days)s days are already filled." ) % { 'days': max_days, }, } return self.render_json_response(ret) return HttpResponseForbidden() @method_decorator([ cache_page(3600), last_modified(CachingService.get_latest_iotd_datetime), cache_control(private=True), vary_on_cookie ], name='dispatch') class IotdArchiveView(ListView): model = Iotd template_name = 'astrobin_apps_iotd/iotd_archive.html' paginate_by = 30 def get_queryset(self): return IotdService().get_iotds()
# -*- coding:utf-8 -*- from django.views.decorators.http import condition, etag, last_modified from django.http import HttpResponse from models import FULL_RESPONSE, LAST_MODIFIED, ETAG def index(request): return HttpResponse(FULL_RESPONSE) index = condition(lambda r: ETAG, lambda r: LAST_MODIFIED)(index) def last_modified_view1(request): return HttpResponse(FULL_RESPONSE) last_modified_view1 = condition(last_modified_func=lambda r: LAST_MODIFIED)(last_modified_view1) def last_modified_view2(request): return HttpResponse(FULL_RESPONSE) last_modified_view2 = last_modified(lambda r: LAST_MODIFIED)(last_modified_view2) def etag_view1(request): return HttpResponse(FULL_RESPONSE) etag_view1 = condition(etag_func=lambda r: ETAG)(etag_view1) def etag_view2(request): return HttpResponse(FULL_RESPONSE) etag_view2 = etag(lambda r: ETAG)(etag_view2)
from django.views.i18n import JavaScriptCatalog from . import views from ...users.forms.auth import AdminAuthenticationForm admin.autodiscover() admin.site.login_form = AdminAuthenticationForm urlpatterns = [ url(r"^", include("social_django.urls", namespace="social")), url(r"^forum/", include("misago.urls", namespace="misago")), url(r"^django-admin/", admin.site.urls), url( r"^django-i18n.js$", cache_page(86400 * 2, key_prefix="misagojsi18n")( last_modified(lambda req, **kw: timezone.now())( JavaScriptCatalog.as_view(packages=["misago"]))), name="django-i18n", ), # django-simple-sso doesn't have namespaces, we can't use namespace here url(r"^sso/", include("misago.sso.urls")), url(r"^forum/test-pagination/$", views.test_pagination, name="test-pagination"), url( r"^forum/test-pagination/(?P<page>[1-9][0-9]*)/$", views.test_pagination, name="test-pagination", ), url( r"^forum/test-paginated-response/$", views.test_paginated_response,
from apps.survey.layer_context import get_group_territory_modification_time ##################################### # PROGRESS PAGE ROUTES ##################################### progress_page = route(GET=do(render_template('survey/progress.html'), v.progress_page)) progress_page_blockface_popup = route( GET=do( render_template('survey/partials/progress_page_blockface_popup.html'), v.progress_page_blockface_popup)) group_borders_geojson = do( last_modified(get_group_territory_modification_time), route(GET=json_api_call(v.group_borders_geojson))) group_popup = route(GET=do(group_request, render_template('survey/partials/group_popup.html'), v.group_popup)) ##################################### # RESERVATION ROUTES ##################################### printable_reservations_map = route( GET=do( login_required, render_template('survey/printable_reservations_map.html'), v.printable_reservations_page))
class CoverArt(View): def __init__(self): self.storage = LOGO_STORAGE @method_decorator(last_modified(_last_modified)) def get(self, request, size, prefix, filename): size = int(size) prefix = get_prefix(filename) target = self.get_thumbnail_path(size, prefix, filename) original = self.get_original_path(prefix, filename) if self.storage.exists(target): return self.send_file(target) if not self.storage.exists(original): logger.warning('Original cover {} not found'.format(original)) raise Http404('Cover Art not available' + original) target_dir = self.get_dir(filename) try: fp = self.storage.open(original, 'rb') im = Image.open(fp) if im.mode not in ('RGB', 'RGBA'): im = im.convert('RGBA') except IOError as ioe: logger.warning('Cover file {} cannot be opened: {}'.format( original, ioe)) raise Http404('Cannot open cover file') from ioe try: im.thumbnail((size, size), Image.ANTIALIAS) resized = im except (struct.error, IOError, IndexError) as ex: # raised when trying to read an interlaced PNG; logger.warning('Could not create thumbnail: %s', str(ex)) # we use the original instead return self.send_file(original) sio = io.BytesIO() try: resized.save(sio, 'JPEG', optimize=True, progression=True, quality=80) except IOError as ex: return self.send_file(original) finally: fp.close() self.storage.save(target, sio) return self.send_file(target) @staticmethod def get_thumbnail_path(size, prefix, filename): return os.path.join('logo', str(size), prefix, filename) @staticmethod def get_dir(filename): return os.path.dirname(filename) @staticmethod def remove_existing_thumbnails(prefix, filename): dirs, _files = LOGO_STORAGE.listdir( 'logo') # TODO: cache list of sizes for size in dirs: if size == 'original': continue path = os.path.join('logo', size, prefix, filename) logger.info('Removing {}'.format(path)) LOGO_STORAGE.delete(path) @staticmethod def get_original_path(prefix, filename): return os.path.join('logo', 'original', prefix, filename) def send_file(self, filename): return HttpResponseRedirect(LOGO_STORAGE.url(filename)) @classmethod def save_podcast_logo(cls, cover_art_url): if not cover_art_url: return try: image_sha1 = hashlib.sha1( cover_art_url.encode('utf-8')).hexdigest() prefix = get_prefix(image_sha1) filename = cls.get_original_path(prefix, image_sha1) dirname = cls.get_dir(filename) # get hash of existing file if LOGO_STORAGE.exists(filename): with LOGO_STORAGE.open(filename, 'rb') as f: old_hash = file_hash(f).digest() else: old_hash = '' logger.info('Logo {}, saving to {}'.format(cover_art_url, filename)) # save new cover art LOGO_STORAGE.delete(filename) source = io.BytesIO(requests.get(cover_art_url).content) LOGO_STORAGE.save(filename, source) # get hash of new file with LOGO_STORAGE.open(filename, 'rb') as f: new_hash = file_hash(f).digest() # remove thumbnails if cover changed if old_hash != new_hash: logger.info('Removing thumbnails') thumbnails = cls.remove_existing_thumbnails(prefix, filename) return cover_art_url except ( ValueError, requests.exceptions.RequestException, socket.error, IOError, ) as e: logger.warning('Exception while updating podcast logo: %s', str(e))
from django.views.generic import TemplateView from django.views import i18n from horizon.test.jasmine import jasmine from horizon import views urlpatterns = [ url(r'^home/$', views.user_home, name='user_home') ] last_modified_date = timezone.now() # Client-side i18n URLconf. urlpatterns.extend([ url(r'^i18n/js/(?P<packages>\S+?)/$', last_modified(lambda req, **kw: last_modified_date)( i18n.JavaScriptCatalog.as_view()), name='jsi18n'), url(r'^i18n/setlang/$', i18n.set_language, name="set_language"), url(r'^i18n/', include('django.conf.urls.i18n')) ]) if settings.DEBUG: urlpatterns.extend([ url(r'^jasmine-legacy/$', TemplateView.as_view( template_name="horizon/jasmine/jasmine_legacy.html"), name='jasmine_tests'), url(r'^jasmine/.*?$', jasmine.dispatcher), ])
context['most_popular_html'] = \ models.MostPopular.get_most_popular_html() return context # LEAVE THIS COMMENTED OUT CODE IN CASE OF EMERGENCY IN # WHICH CODE NEEDS TO CHANGE URGENTLY. def get(self, request, *args, **kwargs): # Add messages here. E.g. messages.add_message(request, messages.INFO, "We're only publishing urgent news until 10 January. Have a safe holiday season.") request = super(HomePage, self).get(request, args, kwargs) return request home_page_view = HomePage.as_view() home_page_view = last_modified(last_article_modified)(home_page_view) class OpinionAnalysisList(ArticleList): def get_queryset(self): return models.Article.objects.list_view().filter( Q(category__name="Opinion") | Q(category__name="Analysis")) def get_context_data(self, **kwargs): context = super(OpinionAnalysisList, self).get_context_data(**kwargs) context['heading'] = "Opinion and Analysis" return context
class CollectionDetail(DetailView, VaryOnCookieMixin): '''View a single collection, with a paginated list of the volumes it includes (volumes sorted by title and then ocm number/volume). ''' model = Collection template_name = 'collection/collection_detail.html' context_object_name = 'collection' display_mode = 'list' @method_decorator(last_modified(view_helpers.collection_modified)) def dispatch(self, *args, **kwargs): return super(CollectionDetail, self).dispatch(*args, **kwargs) def get_object(self, queryset=None): # kwargs are set based on configured url pattern pid = self.kwargs['pid'] repo = Repository(request=self.request) obj = repo.get_object(pid, type=Collection) # if pid doesn't exist or isn't a collection, 404 if not obj.exists or not obj.has_requisite_content_models: raise Http404 return obj def get_context_data(self, **kwargs): context_data = super(CollectionDetail, self).get_context_data() # sort: currently supports title or date added sort = self.request.GET.get('sort', None) if self.request.user.is_authenticated(): notes = Volume.volume_annotation_count(self.request.user) domain = get_current_site(self.request).domain.rstrip('/') if not domain.startswith('http'): domain = 'http://' + domain annotated_volumes = dict([(k.replace(domain, ''), v) for k, v in notes.iteritems()]) else: annotated_volumes = {} # search for all books that are in this collection solr = solr_interface() q = solr.query(content_model=Volume.VOLUME_CMODEL_PATTERN, collection_id=self.object.pid) \ .results_as(SolrVolume) # url parameters for pagination and facet links url_params = self.request.GET.copy() # generate list for display and removal of active filters # NOTE: borrowed from books.view.search display_filters = [] # active filter - only show volumes with pages loaded if 'read_online' in self.request.GET and self.request.GET[ 'read_online']: q = q.query(page_count__gte=2) unfacet_urlopts = url_params.copy() del unfacet_urlopts['read_online'] display_filters.append( ('Read online', '', unfacet_urlopts.urlencode())) else: # generate a facet count for books with pages loaded q = q.facet_query(page_count__gte=2) sort_options = ['title', 'date added'] if sort not in sort_options: # by default, sort by title sort = 'title' if sort == 'title': # sort by title and then by label so multi-volume works should group # together in the correct order q = q.sort_by('title_exact').sort_by('label') elif sort == 'date added': # sort by most recent creation date (newest additions first) q = q.sort_by('-created') # paginate the solr result set paginator = Paginator(q, 30) try: page = int(self.request.GET.get('page', '1')) except ValueError: page = 1 try: results = paginator.page(page) except (EmptyPage, InvalidPage): results = paginator.page(paginator.num_pages) # facets for diplay facet_counts = results.object_list.facet_counts facets = {} if facet_counts.facet_queries: # number of volumes with pages loaded; # facet query is a list of tuple; second value is the count pages_loaded = facet_counts.facet_queries[0][1] if pages_loaded < q.count(): facets['pages_loaded'] = facet_counts.facet_queries[0][1] # url parameters for pagination & sort links url_params = self.request.GET.copy() if 'page' in url_params: del url_params['page'] sort_url_params = self.request.GET.copy() if 'sort' in sort_url_params: del sort_url_params['sort'] context_data.update({ 'items': results.object_list, 'mode': self.display_mode, 'url_params': urlencode(url_params), 'sort_url_params': urlencode(sort_url_params), 'current_url_params': urlencode(self.request.GET.copy()), 'sort': sort, 'sort_options': sort_options, 'annotated_volumes': annotated_volumes, 'facets': facets, # available facets 'filters': display_filters, # active filters # for compatibility with class-based view pagination 'paginator': paginator, 'page_obj': results, }) return context_data
class PageDetail(DetailView, VaryOnCookieMixin): '''View a single page in a book.''' model = Page template_name = 'books/page_detail.html' context_object_name = 'page' @method_decorator(last_modified(view_helpers.page_modified)) def dispatch(self, *args, **kwargs): return super(PageDetail, self).dispatch(*args, **kwargs) def get_object(self, queryset=None): # NOTE: type inferring repository needed to load pages as correct type # of Page (v1.0 or v1.1) repo = TypeInferringRepository(request=self.request) page = repo.get_object(self.kwargs['pid']) if not page.exists or not isinstance(page, Page): raise Http404 return page def get_context_data(self, **kwargs): context_data = super(PageDetail, self).get_context_data() # use solr to find adjacent pages to this one pagequery = self.object.volume.find_solr_pages() # search range around current page order # (+/-1 should probably work, but using 2 to allow some margin for error) pagequery = pagequery.query( page_order__range=(self.object.page_order - 2, self.object.page_order + 2)) # find the index of the current page in the sorted solr result index = 0 prev = nxt = None for p in pagequery: if p['pid'] == self.object.pid: break index += 1 prev = p if len(pagequery) > index + 1: nxt = pagequery[index + 1] # calculates which paginated page the page is part of based on 30 items per page page_chunk = ((self.object.page_order - 1) // 30) + 1 # form for searching in this book form = BookSearch() # currently only pagev1_1 has tei if hasattr(self.object, 'tei') and self.object.tei.exists: # determine scale for positioning OCR text in TEI facsimile # based on original image size in the OCR and image as displayed # - find maximum of width/height long_edge = max(self.object.tei.content.page.width, self.object.tei.content.page.height) # NOTE: using the size from image the OCR was run on, since that # may or may not match the size of the master image loaded in # fedora, but the aspect ration should be kept the same from # original -> repository copy -> scaled copy used for display # - determine scale to convert original size to display size scale = float(SINGLE_PAGE_SIZE) / float(long_edge) logger.debug('page size is %s, long edge is %s, scale is %f' % \ (SINGLE_PAGE_SIZE, long_edge, scale)) else: scale = None context_data.update({ 'next': nxt, 'prev': prev, 'page_chunk': page_chunk, 'form': form, 'scale': scale }) # if user is logged in, check for zotero account and pass # token and user id through for annotation citation if not self.request.user.is_anonymous(): zotero_account = self.request.user.social_auth.filter( provider='zotero').first() if zotero_account: context_data.update({ 'zotero_userid': zotero_account.extra_data['access_token']['userID'], 'zotero_token': zotero_account.extra_data['access_token']['oauth_token'] }) # if user is logged in, check if annotations exist and # search should be enabled context_data['annotation_search_enabled'] = \ self.object.volume.annotations() \ .visible_to(user=self.request.user).exists() return context_data
CategoryOptionsViewSet, basename='category') router.register(r'type-attachment', TypeAttachmentViewSet, basename='type-attachment') router.register(r'thesis-year-options', ThesisYearViewSet, basename='thesis-year') router.register(r'reservation-state-options', ReservationStateOptionsViewSet, basename='reservation-state') router.register(r'thesis-state-options', ThesisStateOptionsViewSet, basename='thesis-state') app_name = 'api' urlpatterns = [ path('v1/', include((router.urls, 'v1'))), path('v1/login', LoginView.as_view()), path('v1/dashboard', DashboardView.as_view()), path('v1/has-perm/<str:perm>', UserPermView.as_view(), name='has-perm'), path('v1/review-pdf-detail/<uuid:pk>', ReviewPdfView.as_view(), name='review-pdf-detail'), path( 'i18n/catalog', last_modified(lambda req, **kw: last_modified_date)( JSONCatalog.as_view(domain='django'))), path('i18n/', include('django.conf.urls.i18n')), ]
from django.http import HttpResponse, HttpResponseForbidden from django.shortcuts import get_object_or_404 from django.views.decorators.http import last_modified, require_safe from django.views.decorators.cache import cache_page from rest_framework import generics from rest_framework.authtoken.models import Token from rest_framework.viewsets import ModelViewSet from synctool.routing import Route from . import models, serializers from .utils import get_last_modified_date, HttpResponseJSON rnasync = Route(api_token=None).app('rna', 'rna') rnasync = last_modified(get_last_modified_date)(rnasync) RNA_JSON_CACHE_TIME = getattr(settings, 'RNA_JSON_CACHE_TIME', 600) def auth_token(request): if request.user.is_active and request.user.is_staff: token, created = Token.objects.get_or_create(user=request.user) return HttpResponse( content=json.dumps({'token': token.key}), content_type='application/json') else: return HttpResponseForbidden() class NoteViewSet(ModelViewSet): queryset = models.Note.objects.all()
def cache(view): return last_modified(lambda req, **kw: last_modified_date)(view)
from . import views from ...users.forms.auth import AdminAuthenticationForm admin.autodiscover() admin.site.login_form = AdminAuthenticationForm urlpatterns = [ url(r"^", include("social_django.urls", namespace="social")), url(r"^forum/", include("misago.urls", namespace="misago")), url(r"^django-admin/", admin.site.urls), url( r"^django-i18n.js$", cache_page(86400 * 2, key_prefix="misagojsi18n")( last_modified(lambda req, **kw: timezone.now())( JavaScriptCatalog.as_view(packages=["misago"]) ) ), name="django-i18n", ), url(r"^forum/test-pagination/$", views.test_pagination, name="test-pagination"), url( r"^forum/test-pagination/(?P<page>[1-9][0-9]*)/$", views.test_pagination, name="test-pagination", ), url( r"^forum/test-paginated-response/$", views.test_paginated_response, name="test-paginated-response", ),
def get_parent_object(self): return get_shared_key(self.request, *self.args, **self.kwargs) def get_doc(self): key = self.get_parent_object() qs = self.model.objects.filter(dataset=key.exhibit.dataset) return qs.values_list("data", flat=True)[0] def check_perms(self): key = self.get_parent_object() return key.exhibit.dataset_available(key.exhibit.owner) def _dataset_modified(r, *a, **kwa): key = get_shared_key(r, *a, **kwa) return key.exhibit.dataset.modified _lm = last_modified(_dataset_modified) shared_dataset_profile_json = _lm(SharedKeyDatasetJSONView.as_view(model=dataset_models.DatasetProfile)) shared_dataset_data_json = _lm(SharedKeyDatasetJSONView.as_view(model=dataset_models.DatasetJSONFile)) shared_dataset_properties_json = _lm(SharedKeyDatasetJSONView.as_view(model=dataset_models.DatasetPropertiesCache)) #-----------------------------------------------------------------------------# # Shared exhibit profile json class SharedExhibitProfileJSONView(BaseJSONView): """ Returns the exhibit profile associated with a particular shared key. There is no permissions check, as the owner of the key is the owner of the exhibit.
content_type='text/html', )), kwargs={'announcements':Announcement.objects.all()}, name='info', ), url(r'^info/links/$', never_cache(TemplateView.as_view( template_name='pages/links.html', content_type='text/html', )), name='links', ), url(r'^about/$', cache_page(60*5)(last_modified(fp_lastmod)(flatpage)), #cache_page(60*5)(flatpage), kwargs={'url': '/about/'}, name='about' ), url(r'^about/privacy/$', cache_page(60*5)(last_modified(fp_lastmod)(flatpage)), kwargs={'url': '/about/privacy/'}, name='privacy' ), url(r'^about/terms/$', cache_page(60*5)(last_modified(fp_lastmod)(flatpage)), kwargs={'url': '/about/terms/'}, name='terms'
class VolumeSearch(ListView): '''Search across all volumes.''' model = Volume template_name = 'books/volume_search.html' paginate_by = 10 context_object_name = 'items' display_mode = 'list' display_filters = [] sort_options = ['relevance', 'title', 'date added'] @method_decorator(last_modified(view_helpers.volumes_modified)) def dispatch(self, *args, **kwargs): return super(VolumeSearch, self).dispatch(*args, **kwargs) def get_queryset(self): self.form = BookSearch(self.request.GET) # sort: currently supports relevance, title, or date added self.sort = self.request.GET.get('sort', None) if self.form.is_valid(): # get list of keywords and phrases terms = self.form.search_terms() solr = solr_interface() # generate queries text and boost-field queries text_query = solr.Q() author_query = solr.Q() title_query = solr.Q() for t in terms: text_query |= solr.Q(t) author_query |= solr.Q(creator=t) title_query |= solr.Q(title=t) q = solr.query().filter(content_model=Volume.VOLUME_CMODEL_PATTERN) \ .query(text_query | author_query**3 | title_query**3) \ .field_limit(SolrVolume.necessary_fields, score=True) \ .results_as(SolrVolume) if self.sort not in self.sort_options: # by default, sort by relevance score self.sort = 'relevance' if self.sort == 'relevance': q = q.sort_by('-score') elif self.sort == 'title': # sort by title and then by label so multi-volume works should group # together in the correct order q = q.sort_by('title_exact').sort_by('label') elif self.sort == 'date added': q = q.sort_by('-created') url_params = self.request.GET.copy() # don't need to facet on collection if we are already filtered on collection if 'collection' not in self.request.GET: q = q.facet_by('collection_label_facet', sort='index', mincount=1) self.display_filters = [] if 'collection' in self.request.GET: filter_val = self.request.GET['collection'] # filter the solr query based on the requested collection q = q.query(collection_label='"%s"' % filter_val) # generate link to remove the facet unfacet_urlopts = url_params.copy() del unfacet_urlopts['collection'] self.display_filters.append( ('collection', filter_val, unfacet_urlopts.urlencode())) # active filter - only show volumes with pages loaded if 'read_online' in self.request.GET and self.request.GET[ 'read_online']: q = q.query(page_count__gte=2) unfacet_urlopts = url_params.copy() del unfacet_urlopts['read_online'] self.display_filters.append( ('Read online', '', unfacet_urlopts.urlencode())) else: # generate a facet count for books with pages loaded q = q.facet_query(page_count__gte=2) return q else: # empty 'queryset' result required by view methods return [] def get_context_data(self): context_data = super(VolumeSearch, self).get_context_data() url_params = self.request.GET.copy() sort_url_params = self.request.GET.copy() if 'sort' in sort_url_params: del sort_url_params['sort'] context_data.update({ 'form': self.form, 'url_params': urlencode(url_params), 'mode': self.display_mode, # list / cover view 'current_url_params': urlencode(self.request.GET.copy()), 'sort': self.sort, 'sort_options': self.sort_options, 'sort_url_params': urlencode(sort_url_params), }) # get facets and annotations IF there are are any search results if context_data['object_list']: # adjust facets as returned from solr for display facet_counts = context_data['object_list'].facet_counts facets = {} collections = facet_counts.facet_fields.get( 'collection_label_facet', []) # only include collections in facet if there are any if collections: facets['collection'] = collections if facet_counts.facet_queries: # number of volumes with pages loaded; # facet query is a list of tuple; second value is the count pages_loaded = facet_counts.facet_queries[0][1] # only display if it is a facet, i.e. not all volumes # in the result set have pages loaded if pages_loaded < context_data['paginator'].count: facets['pages_loaded'] = facet_counts.facet_queries[0][1] # generate list for display and removal of active filters q = self.get_queryset() annotated_volumes = {} if context_data[ 'paginator'].count and self.request.user.is_authenticated( ): notes = Volume.volume_annotation_count(self.request.user) domain = get_current_site(self.request).domain.rstrip('/') if not domain.startswith('https'): domain = 'https://' + domain annotated_volumes = dict([(k.replace(domain, ''), v) for k, v in notes.iteritems()]) context_data.update({ 'facets': facets, # available facets 'filters': self.display_filters, # active filters 'annotated_volumes': annotated_volumes }) return context_data
name="api-notification", kwargs={'action': 'count'}, ), url( r'^api/notification/(?P<app>[\w]+)/(?P<model>[\w]+)/list/$', never_cache( NotificationListAPI.as_view() ), name="api-notification", kwargs={'action': 'list'}, ), url( r'^api/view/(?P<db>[\w-]+)/(?P<cat>[\w-]+)/(?P<view>[\w-]+)/$', cache_page(CACHE_TIME, key_prefix=VERSION)( last_modified(lambda req, **kw: now())( APIViewDetail.as_view() ) ), name="api-view", ), url( r'^api/documents/(?P<app>[\w]+)/(?P<model>[\w]+)/(?P<pk>[0-9]+)/$', APIDocumentsView.as_view({'get': 'list', 'post': 'create'}), name="api-documents", ), url( r'^api/documents/$', APIDocumentsView.as_view({'get': 'list', 'post': 'create'}), name="api-documents", ), url(
if acquisition_type in Image.ACQUISITION_TYPES: queryset = queryset.filter( image__acquisition_type=acquisition_type) return queryset def get_context_data(self, **kwargs): context = super(TopPickBaseView, self).get_context_data(**kwargs) context['source'] = self.request.GET.get('source') context['acquisition_type'] = self.request.GET.get('acquisition_type') return context @method_decorator([ cache_page(600), last_modified(CachingService.get_latest_top_pick_datetime), cache_control(private=True), vary_on_cookie ], name='dispatch') class TopPicksView(TopPickBaseView): model = TopPickArchive template_name = 'top_picks.html' paginate_by = 30 def get_queryset(self): queryset = IotdService().get_top_picks() queryset = self.filter_by_datasource(queryset) queryset = self.filter_by_acquisition_type(queryset) return queryset
from django.views.generic.edit import CreateView from viewshare.apps.share import models from viewshare.apps.exhibit.models import PublishedExhibit from viewshare.apps.share import forms # The last_modified decorator requires a function from viewshare.utilities.views import BaseJSONView def _exhibit_modified(r, *a, **kwa): qs = models.SharedExhibitKey.objects.filter(slug=kwa["slug"]) qs = qs.values_list("exhibit__modified", flat=True)[0] return qs _lm = last_modified(_exhibit_modified) class SharedExhibitDisplayView(DetailView): model = models.SharedExhibitKey template_name = "share/exhibit_display.html" def get_object(self, queryset=None): if queryset is None: queryset = self.get_queryset() queryset = queryset.select_related("exhibit__owner") obj = get_object_or_404(queryset, slug=self.kwargs.get("slug")) return obj
from viewshare.apps.share import models from viewshare.apps.exhibit.models import PublishedExhibit from viewshare.apps.share import forms # The last_modified decorator requires a function from viewshare.utilities.views import BaseJSONView def _exhibit_modified(r, *a, **kwa): qs = models.SharedExhibitKey.objects.filter(slug=kwa["slug"]) qs = qs.values_list("exhibit__modified", flat=True)[0] return qs _lm = last_modified(_exhibit_modified) class SharedExhibitDisplayView(DetailView): model = models.SharedExhibitKey template_name = "share/exhibit_display.html" def get_object(self, queryset=None): if queryset is None: queryset = self.get_queryset() queryset = queryset.select_related("exhibit__owner") obj = get_object_or_404(queryset, slug=self.kwargs.get("slug")) return obj
Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') Including another URLconf 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ from django.contrib import admin from django.urls import path, include from django.conf.urls.i18n import i18n_patterns from authentication.views import index_page, language_changes from .api import router from django.views.i18n import JavaScriptCatalog from django.utils import timezone from django.views.decorators.http import last_modified last_modified_date = timezone.now() urlpatterns = [ path('jsi18n/', last_modified(lambda req, **kw: last_modified_date)( JavaScriptCatalog.as_view()), name='javascript-catalog'), path('', index_page, name="auth_index_view"), path('lang_choose', language_changes, name='language_changes'), path('admin/', admin.site.urls), path('fleet/', include('fleet.urls')), path('authentication/', include('authentication.urls')), path('api/', include(router.urls)) ]
OwnerSlugPermissionMixin, OwnerListView) def get_published_exhibit(request, owner, slug): if not hasattr(request, "exhibit"): request.exhibit = get_object_or_404(models.PublishedExhibit, slug=slug, owner__username=owner) return request.exhibit def get_exhibit_modified(request, *args, **kwargs): return get_published_exhibit(request, kwargs["owner"], kwargs["slug"]).modified exhibit_last_modified = last_modified(get_exhibit_modified) class ExhibitDetailEditView(OwnerSlugPermissionMixin, UpdateView): form_class = forms.UpdateExhibitDetailForm object_perm = "exhibit.can_edit" model = models.PublishedExhibit template_name = "exhibit/edit/exhibit_metadata_form.html" def form_valid(self, form): self.object = form.save() return HttpResponseRedirect(reverse("exhibit_detail", kwargs={ "owner": self.object.owner.username, "slug": self.object.slug
# LEAVE THIS COMMENTED OUT CODE IN CASE OF EMERGENCY IN # WHICH CODE NEEDS TO CHANGE URGENTLY. # def get(self, request, *args, **kwargs): # Add messages here. E.g. # messages.add_message(request, messages.INFO, # "We're only publishing urgent " # "news until 7 January. Have a " # "safe holiday season.") # request = super(HomePage, self).get(request, args, kwargs) # return request home_page_view = HomePage.as_view() home_page_view = last_modified(last_article_modified)(home_page_view) class OpinionAnalysisList(ArticleList): def get_queryset(self): return models.Article.objects.list_view().filter( Q(category__name="Opinion") | Q(category__name="Analysis")) def get_context_data(self, **kwargs): context = super(OpinionAnalysisList, self).get_context_data(**kwargs) context['heading'] = "Opinion and Analysis" return context
def check_perms(self): if not self.request.user.has_perm("dataset.can_view", self.get_parent_object()): return False return True def cache_control_header(self): cache_control = super(DatasetJSONView, self).cache_control_header() if not self.get_parent_object().published: cache_control += ", private" else: cache_control += ", public" return cache_control lmdec = last_modified(lambda request, *args, **kwargs: get_request_instance(request, *args, **kwargs).modified) dataset_profile_json = lmdec(DatasetJSONView.as_view(model=models.DatasetProfile)) dataset_data_json = lmdec(DatasetJSONView.as_view(model=models.DatasetJSONFile)) dataset_properties_json = lmdec(DatasetJSONView.as_view(model=models.DatasetPropertiesCache)) dataset_list_by_owner = OwnerListView.as_view(template_name="dataset/dataset_list_by_owner.html", model=models.Dataset, permission = "dataset.can_view", related=("exhibits","owner")) #----------------------------------------------------------------------------------------------------------------------# # Dataset views
admin.autodiscover() admin.site.login_form = AdminAuthenticationForm urlpatterns = [ url(r'^', include('misago.urls', namespace='misago')), # Javascript translations url( r'^django-i18n.js$', last_modified(lambda req, **kw: timezone.now())( cache_page(86400 * 2, key_prefix='misagojsi18n')( JavaScriptCatalog.as_view( packages=['misago'], ), ), ), name='django-i18n', ), # Uncomment next line if you plan to use Django admin for 3rd party apps #url(r'^django-admin/', admin.site.urls), ] # If debug mode is enabled, include debug toolbar if settings.DEBUG: import debug_toolbar urlpatterns += [
from notification.models import NoticeSetting, NoticeType, NOTICE_MEDIA from persistent_messages.models import Message from rest_framework import viewsets, permissions from rest_framework.decorators import action from rest_framework.renderers import BrowsableAPIRenderer from rest_framework.response import Response from astrobin_apps_notifications.api.filters import NotificationFilter from astrobin_apps_notifications.api.serializers import NotificationSerializer, NoticeSettingSerializers, \ NoticeTypeSerializer from common.permissions import ReadOnly from common.services.caching_service import CachingService @method_decorator([ last_modified(CachingService.get_last_notification_time), cache_control(private=True, no_cache=True), vary_on_headers('Cookie', 'Authorization') ], name='dispatch') class NotificationViewSet(viewsets.ModelViewSet): serializer_class = NotificationSerializer filter_class = NotificationFilter permission_classes = [permissions.IsAuthenticated] renderer_classes = [BrowsableAPIRenderer, CamelCaseJSONRenderer] parser_classes = [CamelCaseJSONParser] http_method_names = ['get', 'post', 'head', 'put'] def get_queryset(self): return Message.objects.filter( user=self.request.user).order_by('-created')
url( r'^api/notification/count/$', never_cache(NotificationCountAPI.as_view()), name="api-notification", kwargs={'action': 'count'}, ), url( r'^api/notification/(?P<app>[\w]+)/(?P<model>[\w]+)/list/$', never_cache(NotificationListAPI.as_view()), name="api-notification", kwargs={'action': 'list'}, ), url( r'^api/view/(?P<db>[\w-]+)/(?P<cat>[\w-]+)/(?P<view>[\w-]+)/$', cache_page(CACHE_TIME, key_prefix=VERSION)( last_modified(lambda req, **kw: now())(APIViewDetail.as_view())), name="api-view", ), url( r'^api/documents/(?P<app>[\w]+)/(?P<model>[\w]+)/(?P<pk>[0-9]+)/$', APIDocumentsView.as_view({ 'get': 'list', 'post': 'create' }), name="api-documents", ), url( r'^api/documents/$', APIDocumentsView.as_view({ 'get': 'list', 'post': 'create'
from django.http import HttpResponse, HttpResponseForbidden from django.shortcuts import get_object_or_404 from django.views.decorators.http import last_modified from rest_framework import generics from rest_framework.authtoken.models import Token from rest_framework.viewsets import ModelViewSet from synctool.routing import Route from . import models, serializers from .utils import get_last_modified_date rnasync = Route(api_token=None).app('rna', 'rna') rnasync = last_modified(get_last_modified_date)(rnasync) def auth_token(request): if request.user.is_active and request.user.is_staff: token, created = Token.objects.get_or_create(user=request.user) return HttpResponse( content=json.dumps({'token': token.key}), content_type='application/json') else: return HttpResponseForbidden() class NoteViewSet(ModelViewSet): queryset = models.Note.objects.all() serializer_class = serializers.NoteSerializer
class VolumeDetail(DetailView, VaryOnCookieMixin): ''' Landing page for a single :class:`~readux.books.models.Volume`. If keyword search terms are specified, searches within the book and finds matching pages. ''' model = Volume template_name = 'books/volume_detail.html' search_template_name = 'books/volume_pages_search.html' context_object_name = 'vol' @method_decorator(last_modified(view_helpers.volume_modified)) @method_decorator(vary_on_headers('X-Requested-With') ) # vary on ajax request def dispatch(self, *args, **kwargs): return super(VolumeDetail, self).dispatch(*args, **kwargs) def get_object(self, queryset=None): # kwargs are set based on configured url pattern pid = self.kwargs['pid'] repo = Repository(request=self.request) vol = repo.get_object(pid, type=Volume) if not vol.exists or not vol.is_a_volume: raise Http404 return vol def get_template_names(self): # search results require a different template if self.form.is_valid(): return self.search_template_name return self.template_name def get_context_data(self, **kwargs): context_data = super(VolumeDetail, self).get_context_data() # sort: currently supports title or date added self.form = BookSearch(self.request.GET) context_data['form'] = self.form # if form is valid, then search within the book and display matching pages # instead of volume info if self.form.is_valid(): terms = self.form.search_terms() solr = solr_interface() query = solr.Q() for t in terms: # NOTE: should this be OR or AND? query |= solr.Q(page_text=t) if t.isnumeric(): query |= solr.Q(page_order=t)**2 query |= solr.Q(identifier=t)**3 # search for pages that belong to this book q = solr.query().filter(content_model=Page.PAGE_CMODEL_PATTERN, isConstituentOf=self.object.uri) \ .query(query) \ .field_limit(['page_order', 'pid', 'identifier'], score=True) \ .highlight('page_text', snippets=3) \ .sort_by('-score').sort_by('page_order') \ .results_as(SolrPage) # return highlighted snippets from page text # sort by relevance and then by page order # paginate the solr result set paginator = Paginator(q, 30) try: page = int(self.request.GET.get('page', '1')) except ValueError: page = 1 try: results = paginator.page(page) except (EmptyPage, InvalidPage): results = paginator.page(paginator.num_pages) # NOTE: highlight snippets are available at # results.object_list.highlighting but are *NOT* currently # getting propagated to solrpage objects # url parameters for pagination url_params = self.request.GET.copy() if 'page' in url_params: del url_params['page'] context_data.update({ 'pages': results, 'url_params': urlencode(url_params), # provided for consistency with class-based view pagination 'paginator': paginator, 'page_obj': results }) else: # if not searching the volume, get annotation count for display # - annotation is only possibly on books with pages loaded if self.object.has_pages: # uses same dictionary lookup form as for browse/search volume annotation_count = self.object.annotation_count( self.request.user) if annotation_count != 0: context_data['annotated_volumes'] = { self.object.get_absolute_url(): annotation_count } # enable annotation search if any annotations are present context_data['annotation_search_enabled'] = bool( annotation_count) return context_data def render_to_response(self, context, **response_kwargs): # return json to ajax request or when requested; # currently used for annotation related pages autocomplete if self.request.is_ajax() or self.request.GET.get('format', '') == 'json': solr_result = context['pages'] highlighting = {} if solr_result.object_list.highlighting: highlighting = solr_result.object_list.highlighting data = [ { 'pid': result.pid, # extra logic to handle records where ARK is not # present (should only happen in dev) 'uri': next( iter([ uri for uri in result['identifier'] if 'ark:' in uri ]), ''), 'label': 'p. %s' % result['page_order'], 'thumbnail': reverse('books:page-image', kwargs={ 'mode': 'mini-thumbnail', 'pid': result.pid, 'vol_pid': self.object.pid }), 'highlights': highlighting.get(result.pid, {}).get('page_text', '') } for result in solr_result.object_list ] return JsonResponse(data, safe=False) else: return super(VolumeDetail, self).render_to_response(context, **response_kwargs)
from kirppu.views import index, MobileRedirect # Uncomment the next two lines to enable the admin: from django.contrib import admin admin.autodiscover() js_packages = ( 'kirppu', ) last_modified_date = timezone.now() urlpatterns = [ path('', index, name='home'), path(r'kirppu/', include('kirppu.urls', namespace="kirppu")), path(r'accounts/', include('kirppuauth.urls', namespace="kirppuauth")), # Uncomment the admin/doc line below to enable admin documentation: # url(r'^admin/doc/', include('django.contrib.admindocs.urls')), # Uncomment the next line to enable the admin: path(r'admin/', admin.site.urls), path(r'i18n/', include('django.conf.urls.i18n')), path(r'jsi18n/', last_modified(lambda req, **kw: last_modified_date)( JavaScriptCatalog.as_view(packages=js_packages)), name="javascript-catalog"), re_path(r'^m/?$', MobileRedirect.as_view()), path('', include('kompassi_oauth2.urls')), ]
from django.views.decorators.http import condition, etag, last_modified from django.http import HttpResponse from .tests import FULL_RESPONSE, LAST_MODIFIED, ETAG def index(request): return HttpResponse(FULL_RESPONSE) index = condition(lambda r: ETAG, lambda r: LAST_MODIFIED)(index) def last_modified_view1(request): return HttpResponse(FULL_RESPONSE) last_modified_view1 = condition(last_modified_func=lambda r: LAST_MODIFIED)(last_modified_view1) def last_modified_view2(request): return HttpResponse(FULL_RESPONSE) last_modified_view2 = last_modified(lambda r: LAST_MODIFIED)(last_modified_view2) def etag_view1(request): return HttpResponse(FULL_RESPONSE) etag_view1 = condition(etag_func=lambda r: ETAG)(etag_view1) def etag_view2(request): return HttpResponse(FULL_RESPONSE) etag_view2 = etag(lambda r: ETAG)(etag_view2)
class CoverArt(View): @method_decorator(last_modified(_last_modified)) def get(self, request, size, prefix, filename): size = int(size) target = self.get_thumbnail(size, prefix, filename) original = self.get_original(prefix, filename) if os.path.exists(target): return self.send_file(target) if not os.path.exists(original): raise Http404('Cover Art not available' + original) target_dir = self.get_dir(target) try: im = Image.open(original) if im.mode not in ('RGB', 'RGBA'): im = im.convert('RGB') except IOError: raise Http404('Cannot open cover file') try: im.thumbnail((size, size), Image.ANTIALIAS) resized = im except (struct.error, IOError, IndexError) as ex: # raised when trying to read an interlaced PNG; logger.warn('Could not create thumbnail: %s', str(ex)) # we use the original instead return self.send_file(original) # If it's a RGBA image, composite it onto a white background for JPEG if resized.mode == 'RGBA': background = Image.new('RGB', resized.size) draw = ImageDraw.Draw(background) draw.rectangle((-1, -1, resized.size[0]+1, resized.size[1]+1), fill=(255, 255, 255)) del draw resized = Image.composite(resized, background, resized) sio = io.BytesIO() try: resized.save(sio, 'JPEG', optimize=True, progression=True, quality=80) except IOError as ex: return self.send_file(original) s = sio.getvalue() fp = open(target, 'wb') fp.write(s) fp.close() return self.send_file(target) # the length of the prefix is defined here and in web/urls.py @staticmethod def get_prefix(filename): return filename[:3] @staticmethod def get_thumbnail(size, prefix, filename): return os.path.join(LOGO_DIR, str(size), prefix, filename) @staticmethod def get_existing_thumbnails(prefix, filename): files = glob(os.path.join(LOGO_DIR, '*', prefix, filename)) return [f for f in files if 'original' not in f] @staticmethod def get_original(prefix, filename): return os.path.join(LOGO_DIR, 'original', prefix, filename) @staticmethod def get_dir(filename): path = os.path.dirname(filename) try: os.makedirs(path) except OSError as ose: if ose.errno != errno.EEXIST: raise return path def send_file(self, filename): try: f = open(filename, 'rb') except IOError: return HttpResponseNotFound() resp = HttpResponse(content_type='image/jpeg') resp.status_code = 200 resp.write(f.read()) return resp
"properties": data_dict["properties_cache__data"], "where": where, "permalink": get_site_url(reverse("exhibit_display", kwargs={'owner': owner, 'slug': slug})), "canvas": canvas_html}) response['Content-Type'] = "application/javascript" response['Cache-Control'] = "no-cache, must-revalidate, public" return response def lmfunc(r, owner, slug): ex = get_published_exhibit(r, owner, slug) if ex.modified > ex.dataset.modified: return ex.modified return ex.dataset.modified embedded_exhibit_view = last_modified(lmfunc)(EmbeddedExhibitView.as_view()) # Exhibit Profile Views class StockExhibitProfileJSONView(View): """Generate the default profile description of an exhibit for a particular dataset and canvas """ def get(self, request, *args, **kwargs): owner = kwargs["owner"] slug = kwargs["slug"] ds = get_object_or_404(models.Dataset, owner__username=owner, slug=slug) user = self.request.user if not user.has_perm("dataset.can_view", ds): raise Http404