def process_request(self, request): try: domain = request.META['HTTP_HOST'] site = cached(lambda: Site.objects.get(domain=domain), ''.join((settings.CACHE_PREFIX, 'dom:', domain)), settings.CACHE_COUNT_TIMEOUT) except (Site.DoesNotExist, KeyError): # If Site ID picked in header, serve that, otherwise default # to Desktop site. site_header = request.META.get('SITE_ID') if site_header in (settings.DESKTOP_SITE_ID, settings.MOBILE_SITE_ID): settings.SITE_ID = site_header else: settings.SITE_ID = settings.DESKTOP_SITE_ID else: settings.SITE_ID = site.id # Detect UA and forward appropriately if this is a known mobile device. if (settings.SITE_ID == settings.DESKTOP_SITE_ID and request.path == '/' and MOBILE_DEVICE_PATTERN.search( request.META.get('HTTP_USER_AGENT', ''))): mobile_site = Site.objects.get(id=settings.MOBILE_SITE_ID) response = HttpResponsePermanentRedirect('%s://%s' % ( 'https' if request.is_secure() else 'http', mobile_site.domain)) response['Vary'] = 'User-Agent' return response # Keep mobile site status in request object request.mobile_site = (settings.SITE_ID == settings.MOBILE_SITE_ID) request.default_app = request.mobile_site and MOBILE or FIREFOX
def category_slider(rand=False, limit=None): def render(): t = env.get_template('browse/helpers/category_slider.html') return jinja2.Markup(t.render(categories=_categories(rand, limit))) return caching.cached( render, 'category-slider-apps-%s-%s' % (rand, limit))
def addon_bayesian_rating(*addons, **kw): def addon_aggregates(): return Addon.objects.valid().aggregate(rating=Avg('average_rating'), reviews=Avg('total_ratings')) log.info('[%s@%s] Updating bayesian ratings.' % (len(addons), addon_bayesian_rating.rate_limit)) avg = caching.cached(addon_aggregates, 'task.bayes.avg', 60 * 60 * 60) # Rating can be NULL in the DB, so don't update it if it's not there. if avg['rating'] is None: return mc = avg['reviews'] * avg['rating'] for addon in Addon.objects.no_cache().filter(id__in=addons): if addon.average_rating is None: # Ignoring addons with no average rating. continue # Update the addon bayesian_rating atomically using F objects (unless # it has no reviews, in which case directly set it to 0). qs = Addon.objects.filter(id=addon.id) if addon.total_ratings: num = mc + F('total_ratings') * F('average_rating') denom = avg['reviews'] + F('total_ratings') qs.update(bayesian_rating=num / denom) else: qs.update(bayesian_rating=0)
def get_features(self): filterset = self.get_lots() key = '%s:%s' % (self.__class__.__name__, filterset.hashkey()) def _get_value(): return super(LotsGeoJSONPolygon, self).get_features() return cached(_get_value, key, 60 * 15)
def addon_bayesian_rating(*addons, **kw): def addon_aggregates(): return Addon.objects.valid().aggregate(rating=Avg('average_rating'), reviews=Avg('total_reviews')) log.info('[%s@%s] Updating bayesian ratings.' % (len(addons), addon_bayesian_rating.rate_limit)) avg = caching.cached(addon_aggregates, 'task.bayes.avg', 60 * 60 * 60) # Rating can be NULL in the DB, so don't update it if it's not there. if avg['rating'] is None: return mc = avg['reviews'] * avg['rating'] for addon in Addon.objects.no_cache().filter(id__in=addons): if addon.average_rating is None: # Ignoring addons with no average rating. continue # Update the addon bayesian_rating atomically using F objects (unless # it has no reviews, in which case directly set it to 0). qs = Addon.objects.filter(id=addon.id) if addon.total_reviews: num = mc + F('total_reviews') * F('average_rating') denom = avg['reviews'] + F('total_reviews') qs.update(bayesian_rating=num / denom) else: qs.update(bayesian_rating=0)
def category_slider(rand=False, limit=None): def render(): t = env.get_template('browse/helpers/category_slider.html') return jinja2.Markup(t.render(categories=_categories(rand, limit))) return render() return caching.cached(render, 'category-slider-apps-%s-%s' % (rand, limit))
def addon_bayesian_rating(*addons, **kw): log.info('[%s@%s] Updating bayesian ratings.' % (len(addons), addon_bayesian_rating.rate_limit)) def qs(): return Webapp.objects.aggregate(rating=Avg('average_rating'), reviews=Avg('total_reviews')) avg = caching.cached(qs, 'task.bayes.avg', 60 * 60 * 60) # Rating can be NULL in the DB, so don't update it if it's not there. if avg['rating'] is None: return mc = avg['reviews'] * avg['rating'] for addon in Webapp.objects.no_cache().filter(id__in=addons): if addon.average_rating is None: # Ignoring addons with no average rating. continue q = Webapp.objects.filter(id=addon.id) if addon.total_reviews: num = mc + F('total_reviews') * F('average_rating') denom = avg['reviews'] + F('total_reviews') q.update(bayesian_rating=num / denom) else: q.update(bayesian_rating=0)
def docs(request): """Docs landing page.""" # Doc of the day dotd = cached(_get_popular_item, 'kuma_docs_dotd', 24*60*60) # Recent updates entries = Entry.objects.filter(feed__shortname='mdc-latest') active_docs = [] for entry in entries: parsed = entry.parsed if not parsed.title.lower().startswith('en/'): continue # L10n: "multiple" refers to more than one author. authorname = (parsed.author if not parsed.author == '(multiple)' else _('(multiple)')) active_docs.append({ 'title': parsed.title[3:].replace('_', ' '), 'link': parsed.link, 'author': authorname }) if len(active_docs) == 5: break review_flag_docs = dict() for tag, description in REVIEW_FLAG_TAGS: review_flag_docs[tag] = (Document.objects .filter_for_review(tag_name=tag) .order_by('-current_revision__created') .all()[:MAX_REVIEW_DOCS]) data = {'active_docs': active_docs, 'review_flag_docs': review_flag_docs, 'dotd': dotd} return jingo.render(request, 'docs/docs.html', data)
def view(request, func): """ This isn't called directly by anything in urls.py. Since all the views in this module are quite similar, each function marked by @section just returns the queryset we should operate on. The rest of the structure is the same. """ qs = func(request).exclude(type=amo.ADDON_PERSONA).distinct() date_ = date.today() form = CategoryForm(request) if form.is_valid(): date_ = form.cleaned_data['date'] or date_ category = form.cleaned_data['category'] if category: qs = qs.filter(categories__slug=category) # These aggregate stats won't change until tomorrow, if ever. tomorrow = date.today() + td(days=1) cache_key = '%s%s' % (qs.query, date_) f = lambda: attach_stats(request, qs, date_) addons = cached(f, cache_key, time.mktime(tomorrow.timetuple())) # Hard limit at 250. Pagination would be friendlier. c = {'addons': addons[:250], 'section': func.__name__, 'form': form, 'sections': get_sections()} return jingo.render(request, 'nick/featured.html', c)
def docs(request): """Docs landing page.""" # Doc of the day dotd = cached(_get_popular_item, 'mdn_docs_dotd', 24*60*60) # Recent updates entries = Entry.objects.filter(feed__shortname='mdc-latest') active_docs = [] for entry in entries: parsed = entry.parsed if not parsed.title.lower().startswith('en/'): continue # L10n: "multiple" refers to more than one author. authorname = (parsed.author if not parsed.author == '(multiple)' else _('(multiple)')) active_docs.append({ 'title': parsed.title[3:].replace('_', ' '), 'link': parsed.link, 'author': authorname }) if len(active_docs) == 5: break data = {'active_docs': active_docs, 'dotd': dotd} return jingo.render(request, 'docs/docs.html', data)
def get_features(self): filterset = self.get_lots() key = '%s:%s' % (self.__class__.__name__, filterset.hashkey()) def _get_value(): features = super(LotsGeoJSONCentroid, self).get_features() shuffle(features) return features return cached(_get_value, key, 60 * 15)
def check_firefox(context=None, ua=None): """ This will return a dictionary of two booleans of whether we're using Firefox and if so whether the version of Firefox supports `navigator.mozApps`. """ if context: ua = context['request'].META.get('HTTP_USER_AGENT') return caching.cached(lambda: _check_firefox(ua), 'check_firefox:%s' % ua)
def get_versions(order=('application', 'version_int')): def f(): apps = amo.APP_USAGE versions = dict((app.id, []) for app in apps) qs = list(AppVersion.objects.order_by(*order) .filter(application__in=versions) .values_list('application', 'version')) for app, version in qs: versions[app].append(version) return apps, versions return caching.cached(f, 'getv' + ''.join(order))
def docs(request): """Docs landing page.""" # Accept ?next parameter for redirects from language selector. if 'next' in request.GET: next = request.GET['next'] # Only accept site-relative paths, not absolute URLs to anywhere. if next.startswith('/'): return HttpResponseRedirect(next) # Doc of the day dotd = cached(_get_popular_item, 'kuma_docs_dotd', 24 * 60 * 60) # Recent updates active_docs = [] if not settings.DEKIWIKI_ENDPOINT: # This doesn't use the MindTouch API directly, but the mdc-latest feed # fetched by feeder does use the feeds API. This data will be stale or # unavailable when MindTouch is disabled, so use a False value here as # a signal to skip it. See also, bug 759368 pass else: entries = Entry.objects.filter(feed__shortname='mdc-latest') for entry in entries: parsed = entry.parsed if not parsed.title.lower().startswith('en/'): continue # L10n: "multiple" refers to more than one author. authorname = (parsed.author if not parsed.author == '(multiple)' else _('(multiple)')) active_docs.append({ 'title': parsed.title[3:].replace('_', ' '), 'link': parsed.link, 'author': authorname }) if len(active_docs) == 5: break review_flag_docs = dict() for tag, description in REVIEW_FLAG_TAGS: review_flag_docs[tag] = (Document.objects.filter_for_review( tag_name=tag).order_by('-current_revision__created').all() [:MAX_REVIEW_DOCS]) data = { 'active_docs': active_docs, 'review_flag_docs': review_flag_docs, 'dotd': dotd } return jingo.render(request, 'docs/docs.html', data)
def docs(request): """Docs landing page.""" # Accept ?next parameter for redirects from language selector. if 'next' in request.GET: next = request.GET['next'] # Only accept site-relative paths, not absolute URLs to anywhere. if next.startswith('/'): return HttpResponseRedirect(next) # Doc of the day dotd = cached(_get_popular_item, 'kuma_docs_dotd', 24*60*60) # Recent updates active_docs = [] if not settings.DEKIWIKI_ENDPOINT: # This doesn't use the MindTouch API directly, but the mdc-latest feed # fetched by feeder does use the feeds API. This data will be stale or # unavailable when MindTouch is disabled, so use a False value here as # a signal to skip it. See also, bug 759368 pass else: entries = Entry.objects.filter(feed__shortname='mdc-latest') for entry in entries: parsed = entry.parsed if not parsed.title.lower().startswith('en/'): continue # L10n: "multiple" refers to more than one author. authorname = (parsed.author if not parsed.author == '(multiple)' else _('(multiple)')) active_docs.append({ 'title': parsed.title[3:].replace('_', ' '), 'link': parsed.link, 'author': authorname }) if len(active_docs) == 5: break review_flag_docs = dict() for tag, description in REVIEW_FLAG_TAGS: review_flag_docs[tag] = (Document.objects .filter_for_review(tag_name=tag) .order_by('-current_revision__created') .all()[:MAX_REVIEW_DOCS]) data = {'active_docs': active_docs, 'review_flag_docs': review_flag_docs, 'dotd': dotd} return jingo.render(request, 'docs/docs.html', data)
def addon_bayesian_rating(*addons, **kw): log.info('[%s@%s] Updating bayesian ratings.' % (len(addons), addon_bayesian_rating.rate_limit)) f = lambda: Addon.objects.aggregate(rating=Avg('average_rating'), reviews=Avg('total_reviews')) avg = caching.cached(f, 'task.bayes.avg', 60 * 60 * 60) mc = avg['reviews'] * avg['rating'] for addon in Addon.uncached.filter(id__in=addons): q = Addon.objects.filter(id=addon.id) if addon.total_reviews: num = mc + F('total_reviews') * F('average_rating') denom = avg['reviews'] + F('total_reviews') q.update(bayesian_rating=num / denom) else: q.update(bayesian_rating=0)
def process_request(self, request): domain = request.META['HTTP_HOST'] try: site = cached(lambda: Site.objects.get(domain=domain), ''.join((settings.CACHE_PREFIX, 'dom:', domain)), settings.CACHE_COUNT_TIMEOUT) except (Site.DoesNotExist, KeyError): # Serve Desktop site. settings.SITE_ID = settings.DESKTOP_SITE_ID else: settings.SITE_ID = site.id # Keep mobile site status in request object request.mobile_site = (settings.SITE_ID == settings.MOBILE_SITE_ID) request.default_app = request.mobile_site and MOBILE or FIREFOX
def docs(request): """Docs landing page.""" # Accept ?next parameter for redirects from language selector. if 'next' in request.GET: next = request.GET['next'] # Only accept site-relative paths, not absolute URLs to anywhere. if next.startswith('/'): return HttpResponseRedirect(next) # Doc of the day dotd = cached(_get_popular_item, 'kuma_docs_dotd', 24 * 60 * 60) # Recent updates active_docs = [] entries = Entry.objects.filter(feed__shortname='mdc-latest') for entry in entries: parsed = entry.parsed if not parsed.title.lower().startswith('en/'): continue # L10n: "multiple" refers to more than one author. authorname = (parsed.author if not parsed.author == '(multiple)' else _('(multiple)')) active_docs.append({ 'title': parsed.title[3:].replace('_', ' '), 'link': parsed.link, 'author': authorname }) if len(active_docs) == 5: break review_flag_docs = dict() for tag, description in REVIEW_FLAG_TAGS: review_flag_docs[tag] = (Document.objects.filter_for_review( tag_name=tag).order_by('-current_revision__created').all() [:MAX_REVIEW_DOCS]) data = { 'active_docs': active_docs, 'review_flag_docs': review_flag_docs, 'dotd': dotd } return render(request, 'docs/docs.html', data)
def docs(request): """Docs landing page.""" # Accept ?next parameter for redirects from language selector. if 'next' in request.GET: next = request.GET['next'] # Only accept site-relative paths, not absolute URLs to anywhere. if next.startswith('/'): return HttpResponseRedirect(next) # Doc of the day dotd = cached(_get_popular_item, 'kuma_docs_dotd', 24*60*60) # Recent updates active_docs = [] entries = Entry.objects.filter(feed__shortname='mdc-latest') for entry in entries: parsed = entry.parsed if not parsed.title.lower().startswith('en/'): continue # L10n: "multiple" refers to more than one author. authorname = (parsed.author if not parsed.author == '(multiple)' else _('(multiple)')) active_docs.append({ 'title': parsed.title[3:].replace('_', ' '), 'link': parsed.link, 'author': authorname }) if len(active_docs) == 5: break review_flag_docs = dict() for tag, description in REVIEW_FLAG_TAGS: review_flag_docs[tag] = (Document.objects .filter_for_review(tag_name=tag) .order_by('-current_revision__created') .all()[:MAX_REVIEW_DOCS]) data = {'active_docs': active_docs, 'review_flag_docs': review_flag_docs, 'dotd': dotd} return render(request, 'docs/docs.html', data)
def process_request(self, request): try: domain = request.META['HTTP_HOST'] site = cached(lambda: Site.objects.get(domain=domain), ''.join((settings.CACHE_PREFIX, 'dom:', domain)), settings.CACHE_COUNT_TIMEOUT) except (Site.DoesNotExist, KeyError): # If Site ID picked in header, serve that, otherwise default # to Desktop site. site_header = request.META.get('SITE_ID') if site_header in (settings.DESKTOP_SITE_ID, settings.MOBILE_SITE_ID): settings.SITE_ID = site_header else: settings.SITE_ID = settings.DESKTOP_SITE_ID else: settings.SITE_ID = site.id # Keep mobile site status in request object request.mobile_site = (settings.SITE_ID == settings.MOBILE_SITE_ID) request.default_prod = request.mobile_site and MOBILE or FIREFOX
def process_request(self, request): try: domain = request.META['HTTP_HOST'] site = cached(lambda: Site.objects.get(domain=domain), ''.join( (settings.CACHE_PREFIX, 'dom:', domain)), settings.CACHE_COUNT_TIMEOUT) except (Site.DoesNotExist, KeyError): # If Site ID picked in header, serve that, otherwise default # to Desktop site. site_header = request.META.get('SITE_ID') if site_header in (settings.DESKTOP_SITE_ID, settings.MOBILE_SITE_ID): settings.SITE_ID = site_header else: settings.SITE_ID = settings.DESKTOP_SITE_ID else: settings.SITE_ID = site.id # Keep mobile site status in request object request.mobile_site = (settings.SITE_ID == settings.MOBILE_SITE_ID) request.default_prod = request.mobile_site and MOBILE or FIREFOX
def addon_bayesian_rating(*addons, **kw): def addon_aggregates(): return Addon.objects.aggregate(rating=Avg("average_rating"), reviews=Avg("total_reviews")) log.info("[%s@%s] Updating bayesian ratings." % (len(addons), addon_bayesian_rating.rate_limit)) avg = caching.cached(addon_aggregates, "task.bayes.avg", 60 * 60 * 60) # Rating can be NULL in the DB, so don't update it if it's not there. if avg["rating"] is None: return mc = avg["reviews"] * avg["rating"] for addon in Addon.objects.no_cache().filter(id__in=addons): if addon.average_rating is None: # Ignoring addons with no average rating. continue q = Addon.objects.filter(id=addon.id) if addon.total_reviews: num = mc + F("total_reviews") * F("average_rating") denom = avg["reviews"] + F("total_reviews") q.update(bayesian_rating=num / denom) else: q.update(bayesian_rating=0)
def addon_bayesian_rating(*addons, **kw): log.info('[%s@%s] Updating bayesian ratings.' % (len(addons), addon_bayesian_rating.rate_limit)) f = lambda: Addon.objects.aggregate(rating=Avg('average_rating'), reviews=Avg('total_reviews')) avg = caching.cached(f, 'task.bayes.avg', 60 * 60 * 60) # Rating can be NULL in the DB, so don't update it if it's not there. if avg['rating'] is None: return mc = avg['reviews'] * avg['rating'] for addon in Addon.objects.no_cache().filter(id__in=addons): if addon.average_rating is None: # Ignoring addons with no average rating. continue q = Addon.objects.filter(id=addon.id) if addon.total_reviews: num = mc + F('total_reviews') * F('average_rating') denom = avg['reviews'] + F('total_reviews') q.update(bayesian_rating=num / denom) else: q.update(bayesian_rating=0)
def side_nav(context, addon_type, category=None): app = context['request'].APP.id cat = str(category.id) if category else 'all' return caching.cached(lambda: _side_nav(context, addon_type, category), 'side-nav-%s-%s-%s' % (app, addon_type, cat))
def site_nav(context): app = context['request'].APP.id return caching.cached(lambda: _site_nav(context), 'site-nav-%s' % app)
def category_slider(rand=False, limit=None): return _categories(rand, limit) return caching.cached(lambda: _categories(rand), 'category-slider-apps-%s-%s' % (rand, limit))
def side_nav(context, addon_type): app = context['request'].APP.id return caching.cached(lambda: _side_nav(context, addon_type), 'side-nav-%s' % app)
def _category_personas(qs, limit): def f(): return randslice(qs, limit=limit) key = 'cat-personas:' + qs.query_key() return caching.cached(f, key)
def category_slider(rand=False, limit=None): # TODO: Remove this eventually. return _categories(rand, limit) return caching.cached(lambda: _categories(rand), 'category-slider-apps-%s-%s' % (rand, limit))
def apps_site_nav(context): return caching.cached(lambda: _apps_site_nav(context), 'site-nav-apps')
def side_nav(context, addon_type, category=None): app = context["request"].APP.id cat = str(category.id) if category else "all" return caching.cached( lambda: _side_nav(context, addon_type, category), "side-nav-%s-%s-%s" % (app, addon_type, cat) )
def site_nav(context): app = context["request"].APP.id return caching.cached(lambda: _site_nav(context), "site-nav-%s" % app)
def side_nav(context, addon_type, category=None, impala=False): app = context['request'].APP.id imp = 'impala' if impala else 'old' cat = str(category.id) if category else 'all' return caching.cached(lambda: _side_nav(context, addon_type, category, impala), 'side-nav-%s-%s-%s-%s' % (app, addon_type, cat, impala))
def check_firefox(ua): return caching.cached(lambda: _check_firefox(ua), 'check_firefox:%s' % ua)
def category_slider_themes(): return caching.cached(lambda: _categories_themes(), 'category-slider-themes')
def category_slider_themes(): return caching.cached(lambda: _categories_themes(), "category-slider-themes")
def site_nav(context): return caching.cached(lambda: _site_nav(context), 'site-nav')
def _category_personas(qs, limit): f = lambda: randslice(qs, limit=limit) key = 'cat-personas:' + qs.query_key() return caching.cached(f, key)
def category_slider(): return caching.cached(lambda: _categories(), 'category-slider-apps')
def category_slider_themes(): return caching.cached(_categories_themes, 'category-slider-themes')