Skip to content

Commit

Permalink
[#1258] Project list optimizations
Browse files Browse the repository at this point in the history
- Moved code for getting the project list to a decorator that is
  reusable but not affects all requests.
- Disabled the donation button in the project list.
- Added a db_index on the Publishingstatus model.
- Cleaned up a lot of markup with help of linter.
  • Loading branch information
kardan committed Mar 10, 2015
1 parent 7a79901 commit 5594782
Show file tree
Hide file tree
Showing 8 changed files with 826 additions and 115 deletions.
46 changes: 22 additions & 24 deletions akvo/rsr/context_processors.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,29 @@
# -*- coding: utf-8 -*-

"""
Akvo RSR is covered by the GNU Affero General Public License.
See more details in the license.txt file located at the root folder of the
Akvo RSR module. For additional details on the GNU license please
see < http://www.gnu.org/licenses/agpl.html >.
Akvo RSR is covered by the GNU Affero General Public License.
See more details in the license.txt file located at the root folder of the
Akvo RSR module. For additional details on the GNU license please see
< http://www.gnu.org/licenses/agpl.html >.
"""

import django

from django.conf import settings
from django.contrib.sites.models import get_current_site

from akvo.rsr.models import Project


def extra_context(request, protocol="http"):
"""Add information to the request context."""
current_site = get_current_site(request)
django_version = django.get_version()
deploy_tag = getattr(settings, 'DEPLOY_TAG', 'Unknown')
deploy_branch = getattr(settings, 'DEPLOY_BRANCH', 'Unknown')
deploy_commit_id = getattr(settings, 'DEPLOY_COMMIT_ID', 'Unknown')
deploy_commit_full_id = getattr(settings, 'DEPLOY_COMMIT_FULL_ID', 'Unknown')
deploy_commit_full_id = getattr(
settings, 'DEPLOY_COMMIT_FULL_ID', 'Unknown')

template_context = dict(
return dict(
current_site=current_site,
django_version=django_version,
deploy_tag=deploy_tag,
Expand All @@ -33,33 +32,32 @@ def extra_context(request, protocol="http"):
deploy_commit_full_id=deploy_commit_full_id
)

return template_context


def get_current_path_without_lang(request):
"""Return current path without lang."""
path = request.get_full_path()
path_bits = path.split('/')
path = '/'.join(path_bits[2:])
return {'current_path_without_lang': path}


def extra_pages_context(request):
"""Add context information of an RSR Page"""
"""Add context information of an RSR Page."""
if request.rsr_page:
page = request.rsr_page

# Check if only projects of the partner should be shown or all projects
if page.partner_projects:
projects = page.organisation.published_projects().prefetch_related('locations')
else:
projects = Project.objects.all().published().prefetch_related('locations')

# Check if keywords have been specified for the partner site and filter projects based on keywords if so
if page.keywords.all():
if page.exclude_keywords:
projects = projects.exclude(keywords__in=page.keywords.all())
else:
projects = projects.filter(keywords__in=page.keywords.all())
# if page.partner_projects:
# projects = page.organisation.published_projects().prefetch_related('locations')
# else:
# projects = Project.objects.all().published().prefetch_related('locations')
#
# # Check if keywords have been specified for the partner site and filter projects based on keywords if so
# if page.keywords.all():
# if page.exclude_keywords:
# projects = projects.exclude(keywords__in=page.keywords.all())
# else:
# projects = projects.filter(keywords__in=page.keywords.all())

return {
'rsr_page': page,
Expand All @@ -71,7 +69,7 @@ def extra_pages_context(request):
'stylesheet': page.stylesheet,
'akvoapp_root_url': request.akvoapp_root_url,
'domain_url': request.domain_url,
'projects_qs': projects.latest_update_fields().order_by('-id'),
# 'projects_qs': projects.latest_update_fields().order_by('-id'),
'no_facebook': not page.facebook_button,
'facebook_app_id': page.facebook_app_id,
'no_twitter': not page.twitter_button,
Expand Down
93 changes: 54 additions & 39 deletions akvo/rsr/middleware.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
# -*- coding: utf-8 -*-

"""
Akvo RSR is covered by the GNU Affero General Public License.
See more details in the license.txt file located at the root folder of the
Akvo RSR module. For additional details on the GNU license please
see < http://www.gnu.org/licenses/agpl.html >.
Akvo RSR is covered by the GNU Affero General Public License.
See more details in the license.txt file located at the root folder of the
Akvo RSR module. For additional details on the GNU license please see
< http://www.gnu.org/licenses/agpl.html >.
"""

from django.conf import settings
from django.contrib.sites.models import Site
from django.core.urlresolvers import (LocaleRegexURLResolver, is_valid_path,
get_resolver, set_urlconf)
get_resolver)
from django.http import HttpResponseRedirect
from django.middleware.locale import LocaleMiddleware
from django.shortcuts import redirect
Expand All @@ -29,13 +28,12 @@
"PagesRouterMiddleware",
"get_domain",
"get_or_create_site",
"is_partner_site_instance",
"is_rsr_instance",
"make_tls_property"]


def make_tls_property(default=None):
"Creates a class-wide instance property with a thread-specific value."
"""Create a class-wide instance property with a thread-specific value."""
class TLSProperty(object):
def __init__(self):
from threading import local
Expand All @@ -60,17 +58,16 @@ def _set_value(self, value):


def _patch_setattr(obj):
"""Purpose of this is to allow changes to settings object again after it is
changed to tls property.
"""Allow changes to tls property objects.
Without this patch the following is not possible::
settings.SITE_ID = 1
settings.SITE_ID = 42
assert settings.SITE_ID == 42 # this fails without this patch
settings.SITE_ID = 1
settings.SITE_ID = 42
assert settings.SITE_ID == 42 # this fails without this patch
"""
old_setattr = obj.__setattr__

def wrap_setattr(self, name, value):
try:
getattr(self.__class__, name).value = value
Expand All @@ -92,6 +89,7 @@ def wrap_setattr(self, name, value):


def get_domain(request):
"""Get domain from request."""
original_domain = request.get_host().split(":")[0]
if original_domain == "rsr.akvo.org":
domain = original_domain
Expand All @@ -102,24 +100,31 @@ def get_domain(request):


def is_rsr_instance(hostname):
"""."""
return any([site.search(hostname) for site in RSR_SITE_REGEXPS])


def is_rsr_page_instance(hostname):
"""."""
return any([site.search(hostname) for site in PARTNER_SITE_REGEXPS])


def get_or_create_site(domain):
"""Make sure we have a matching SITE object.
As a result of an issue(1) we need to ensure that we don't
delete the fixture should we find duplicates
There is no guaranteed ordering(2) we should explicitly order them in such
a way that the fixture would appear first, i.e. by ensuring 'ORDER BY id
ASC'.
(1) https://github.com/akvo/akvo-provisioning/issues/29
(2) http://stackoverflow.com/questions/7163640/
what-is-the-default-order-of-a-list-returned-from-a-django-filter-call
"""
if domain.startswith('www.'):
domain = domain[4:]

# As a result of an issue(1) we need to ensure that we don't
# delete the fixture should we find duplicates
# There is no guaranteed ordering(2) we should explicitly order them in such
# a way that the fixture would appear first, i.e. by ensuring 'ORDER BY id ASC'
#
# (1) https://github.com/akvo/akvo-provisioning/issues/29
# (2) http://stackoverflow.com/questions/7163640/what-is-the-default-order-of-a-list-returned-from-a-django-filter-call
sites = Site.objects.filter(domain=domain).order_by('id')
if sites.count() >= 1:
site, duplicates = sites[0], sites[1:]
Expand All @@ -134,8 +139,10 @@ def get_or_create_site(domain):

class PagesRouterMiddleware(object):

def process_request(self, request, cname_domain=False, rsr_page=None):
"""Dispatch to normal or RSR page based on request domain."""

def process_request(self, request, cname_domain=False, rsr_page=None):
"""."""
domain = get_domain(request)

if is_rsr_instance(domain):
Expand Down Expand Up @@ -163,7 +170,8 @@ def process_request(self, request, cname_domain=False, rsr_page=None):

if rsr_page is not None and rsr_page.enabled:
if cname_domain:
rsr_page_domain = getattr(settings, 'AKVOAPP_DOMAIN', 'akvoapp.org')
rsr_page_domain = getattr(
settings, 'AKVOAPP_DOMAIN', 'akvoapp.org')
else:
rsr_page_domain = ".".join(domain.split(".")[1:])
request.rsr_page = settings.RSR_PAGE = rsr_page
Expand All @@ -178,25 +186,28 @@ def process_request(self, request, cname_domain=False, rsr_page=None):
request.domain_url = "http://%s" % settings.RSR_DOMAIN
site = get_or_create_site(domain)
settings.SITE_ID = site.id
return
return None


class PagesLocaleMiddleware(LocaleMiddleware):

"""
Partner sites aware version of Django's LocaleMiddleware. Since we
swap out the root urlconf for a partner sites specific one, and the
original Django LocaleMiddleware didn't like that.
Partner sites aware version of Django's LocaleMiddleware.
Since we swap out the root urlconf for a partner sites specific one, and
the original Django LocaleMiddleware didn't like that.
"""

def process_request(self, request):
"""."""
check_path = self.is_language_prefix_patterns_used(request)
language = translation.get_language_from_request(
request, check_path=check_path)
translation.activate(language)
request.LANGUAGE_CODE = translation.get_language()

def process_response(self, request, response):
"""."""
# First set the default language, this will be used if there is none
# in the path
default_language = getattr(request, 'default_language', '')
Expand Down Expand Up @@ -224,8 +235,11 @@ def process_response(self, request, response):
return response

def is_language_prefix_patterns_used(self, request):
"""Returns `True` if the `LocaleRegexURLResolver` is used
at root level of the urlpatterns, else it returns `False`."""
"""Return True if languge prefix is used.
Return `True` if the `LocaleRegexURLResolver` is used
at root level of the urlpatterns, else it returns `False`.
"""
urlconf = getattr(request, 'urlconf', None)
for url_pattern in get_resolver(urlconf).url_patterns:
if isinstance(url_pattern, LocaleRegexURLResolver):
Expand All @@ -234,21 +248,22 @@ def is_language_prefix_patterns_used(self, request):


class ExceptionLoggingMiddleware(object):
""" Used to log exceptions on production systems
"""
def process_exception(self, request, exception):

"""Used to log exceptions on production systems."""

def process_exception(self, request, exception):
logging.exception('Exception handling request for ' + request.path)


class RSRVersionHeaderMiddleware(object):
""" Add a response header with RSR version info
"""

"""Add a response header with RSR version info."""

def process_response(self, request, response):
context = extra_context(request)
response['X-RSR-Version'] = "Tag:{deploy_tag} Commit:{deploy_commit_id} Branch:{deploy_branch}".format(
deploy_tag=context['deploy_tag'],
deploy_commit_id=context['deploy_commit_id'],
deploy_branch=context['deploy_branch'],
)

response['X-RSR-Version'] = "tag={}, commit={}, branch={}".format(
context['deploy_tag'],
context['deploy_commit_id'],
context['deploy_branch'])
return response
Loading

0 comments on commit 5594782

Please sign in to comment.