Changeset - 07faf5cebca9
www/conservancy/__init__.py
Show inline comments
...
 
@@ -2,7 +2,10 @@ import hashlib
 

	
 
from django.conf import settings
 
from django.shortcuts import render_to_response
 
from django.template import RequestContext
 

	
 
# This is backwards compatibilty support for a custom function we wrote
 
# ourselves that is no longer necessary in modern Django.
 
from django.shortcuts import render as render_template_with_context
 

	
 
class ParameterValidator(object):
 
    def __init__(self, given_hash_or_params, params_hash_key=None):
...
 
@@ -42,7 +45,2 @@ class ParameterValidator(object):
 
    def fail(self):
 
        self.valid = False
 

	
 

	
 
def render_template_with_context(request, template_path, context_dict):
 
    return render_to_response(template_path, context_dict,
 
                              context_instance=RequestContext(request))
www/conservancy/apps/blog/models.py
Show inline comments
 
from django.db import models
 
from django.conf import settings
 
from conservancy import bsoup
 
from conservancy.apps.staff.models import Person
 
from datetime import datetime, timedelta
...
 
@@ -19,5 +20,5 @@ class EntryTag(models.Model):
 
        return u"/blog/?tag=%s" % self.slug
 

	
 
class Entry(models.Model):
 
class Entry(models.Model, bsoup.SoupModelMixin):
 
    """Blog entry"""
 

	
...
 
@@ -39,4 +40,6 @@ class Entry(models.Model):
 
        get_latest_by = 'pub_date'
 

	
 
    SOUP_ATTRS = ['body']
 

	
 
    def __unicode__(self):
 
        return self.headline
www/conservancy/apps/blog/urls.py
Show inline comments
 
from django.conf.urls import patterns, url, include
 
from django.conf.urls import url, include
 
from conservancy.apps.blog.models import Entry, EntryTag # relative import
 
from conservancy.apps.staff.models import Person
 
from datetime import datetime
 
from conservancy.apps.blog.views import last_name, BlogYearArchiveView, BlogMonthArchiveView, BlogDayArchiveView, BlogDateDetailView
 
from conservancy.apps.blog.views import last_name, BlogYearArchiveView, BlogMonthArchiveView, BlogDayArchiveView, BlogDateDetailView, custom_index, query
 

	
 
extra_context = {}
...
 
@@ -13,21 +13,12 @@ info_dict = {
 
}
 

	
 
# urlpatterns = patterns('django.views.generic.date_based',
 
urlpatterns = patterns('',
 
   # (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/(?P<slug>[-\w]+)/$', 'object_detail', dict(info_dict, slug_field='slug')),
 
   # (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/$', 'archive_day', info_dict),
 
   # (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$', 'archive_month', info_dict),
 
   # (r'^(?P<year>\d{4})/$', 'archive_year', dict(info_dict,
 
   #                                              make_object_list=True)),
 
   (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/(?P<slug>[-\w]+)/$', BlogDateDetailView.as_view(**info_dict)),
 
   (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/$', BlogDayArchiveView.as_view(**info_dict)),
 
   (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$', BlogMonthArchiveView.as_view(**info_dict)),
 
   (r'^(?P<year>\d{4})/$', BlogYearArchiveView.as_view(**info_dict)),
 
)
 

	
 
urlpatterns += patterns('conservancy.apps.blog.views',
 
                        (r'^/?$', 'custom_index', dict(info_dict, paginate_by=4)),
 
   (r'^query/$', 'query'),
 
)
 
urlpatterns = [
 
    url(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/(?P<slug>[-\w]+)/$', BlogDateDetailView.as_view(**info_dict)),
 
    url(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/$', BlogDayArchiveView.as_view(**info_dict)),
 
    url(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$', BlogMonthArchiveView.as_view(**info_dict)),
 
    url(r'^(?P<year>\d{4})/$', BlogYearArchiveView.as_view(**info_dict)),
 
    url(r'^/?$', custom_index, dict(info_dict, paginate_by=4)),
 
    url(r'^query/$', query),
 
]
 

	
 
# Code to display authors and tags on each blog page
www/conservancy/apps/blog/views.py
Show inline comments
...
 
@@ -5,6 +5,5 @@ from django.views.generic.dates import YearArchiveView, MonthArchiveView, DayArc
 
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
 
from conservancy.apps.staff.models import Person
 
from django.shortcuts import get_object_or_404, render_to_response
 
from django.template import RequestContext
 
from django.shortcuts import get_object_or_404, render
 
from datetime import datetime
 

	
...
 
@@ -66,5 +65,5 @@ def custom_index(request, queryset, *args, **kwargs):
 
    extra_context['blog_entries'] = blog_entries
 

	
 
    return render_to_response('blog/entry_list.html', extra_context, context_instance=RequestContext(request))
 
    return render(request, 'blog/entry_list.html', extra_context)
 

	
 
def techblog_redirect(request):
...
 
@@ -104,6 +103,5 @@ def query(request):
 
                         key=last_name)
 
        tags = EntryTag.objects.all().order_by('label')
 
        return render_to_response('blog/query.html',
 
                                  {'authors': authors, 'tags': tags}, context_instance=RequestContext(request))
 
        return render(request, 'blog/query.html', {'authors': authors, 'tags': tags})
 

	
 
def relative_redirect(request, path):
www/conservancy/apps/contacts/views.py
Show inline comments
 
from django.shortcuts import render_to_response
 
from django.template import RequestContext
 
from django.shortcuts import render
 
from django import forms
 
from conservancy.apps.contacts.models import ContactEntry
...
 
@@ -19,9 +18,7 @@ def subscribe(request):
 
        if form.is_valid():
 
            form.save()
 
            return render_to_response('contacts/subscribe_success.html',
 
                                      {'form': form.cleaned_data}, context_instance=RequestContext(request))
 
            return render(request, 'contacts/subscribe_success.html', {'form': form.cleaned_data})
 
    else:
 
        form = ContactEntryForm()
 

	
 
    return render_to_response('contacts/subscribe.html',
 
                              {'form': form}, context_instance=RequestContext(request))
 
    return render(request, 'contacts/subscribe.html', {'form': form})
www/conservancy/apps/contractpatch/urls.py
Show inline comments
 
from django.conf.urls import patterns, url, include
 
from django.conf.urls import url, include
 
from conservancy.apps.contractpatch import views as cpatch_views
 

	
 
urlpatterns = patterns(
 
    '',
 
    (r'', 'conservancy.apps.contractpatch.views.index'),
 
)
 
urlpatterns = [
 
    url(r'', cpatch_views.index),
 
]
www/conservancy/apps/events/views.py
Show inline comments
 
# from django.views.generic.list_detail import object_list
 
from django.shortcuts import render_to_response
 
from django.template import RequestContext
 
from django.shortcuts import render
 
from django.http import Http404, HttpResponse
 
from django.template import loader
...
 
@@ -22,5 +21,5 @@ def event_detail(request, year, slug, queryset, **kwargs):
 
    except ObjectDoesNotExist:
 
        raise Http404, "Event does not exist"
 
    return render_to_response('events/event_detail.html', {'event': event}, context_instance=RequestContext(request))
 
    return render(request, 'events/event_detail.html', {'event': event})
 

	
 
def custom_index(request, queryset, *args, **kwargs):
www/conservancy/apps/news/models.py
Show inline comments
 
from django.db import models
 
from django.conf import settings
 
from conservancy import bsoup
 
from conservancy.apps.staff.models import Person
 
from conservancy.apps.events.models import Event
...
 
@@ -6,5 +7,5 @@ from django.contrib.sites.models import Site
 
from datetime import datetime, timedelta
 

	
 
class PressRelease(models.Model):
 
class PressRelease(models.Model, bsoup.SoupModelMixin):
 
    """News release model"""
 

	
...
 
@@ -25,4 +26,6 @@ class PressRelease(models.Model):
 
        get_latest_by = "pub_date"
 

	
 
    SOUP_ATTRS = ['summary', 'body']
 

	
 
    def __unicode__(self):
 
        return self.headline
www/conservancy/apps/news/templatetags/fill_url.py
Show inline comments
 
new file 100644
 
import urlparse
 

	
 
from django import template
 

	
 
register = template.Library()
 

	
 
@register.filter(name='fill_url')
 
def fill_url(given_url, base_url):
 
    """"Fill out" missing pieces of one URL from another.
 

	
 
    This function parses the given URL, and if it's missing any pieces
 
    (scheme, netloc, etc.), it fills those in from the base URL.
 
    Typical usage is "/URL/path"|fill_url:"https://hostname/"
 
    to generate "https://hostname/URL/path".
 
    """
 
    given_parts = urlparse.urlsplit(given_url)
 
    base_parts = urlparse.urlsplit(base_url)
 
    return urlparse.urlunsplit(
 
        given_part or base_part for given_part, base_part in zip(given_parts, base_parts)
 
    )
www/conservancy/apps/news/urls.py
Show inline comments
...
 
@@ -18,8 +18,8 @@
 
# "AGPLv3".  If not, see <http://www.gnu.org/licenses/>.
 

	
 
from django.conf.urls import patterns, url, include
 
from django.conf.urls import url, include
 
from django.conf import settings
 
from conservancy.apps.news.models import PressRelease, ExternalArticle
 
from conservancy.apps.news.views import NewsYearArchiveView, NewsMonthArchiveView, NewsDayArchiveView, NewsDateDetailView
 
from conservancy.apps.news.views import NewsYearArchiveView, NewsMonthArchiveView, NewsDayArchiveView, NewsDateDetailView, listing
 

	
 
info_dict = {
...
 
@@ -32,17 +32,9 @@ external_article_dict = {
 
}
 

	
 
urlpatterns = patterns('',
 
#    (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/(?P<slug>[-\w]+)/$', 'conservancy.apps.news.views.object_detail', info_dict),
 
   (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/(?P<slug>[-\w]+)/$', NewsDateDetailView.as_view(**info_dict)),
 
#   (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/$', 'conservancy.apps.news.views.archive_day', info_dict),
 
   (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/$', NewsDayArchiveView.as_view(**info_dict)),
 
#   (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$', 'conservancy.apps.news.views.archive_month', info_dict),
 
   (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$', NewsMonthArchiveView.as_view(**info_dict)),
 
#   (r'^(?P<year>\d{4})/$', 'conservancy.apps.news.views.archive_year',
 
#    dict(info_dict, make_object_list=True)),
 
   (r'^(?P<year>\d{4})/$', NewsYearArchiveView.as_view(**info_dict)),
 
)
 

	
 
urlpatterns += patterns('',
 
   (r'^/?$', 'conservancy.apps.news.views.listing', dict(info_dict, paginate_by=6)),
 
)
 
urlpatterns = [
 
   url(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/(?P<slug>[-\w]+)/$', NewsDateDetailView.as_view(**info_dict)),
 
   url(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/$', NewsDayArchiveView.as_view(**info_dict)),
 
   url(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$', NewsMonthArchiveView.as_view(**info_dict)),
 
   url(r'^(?P<year>\d{4})/$', NewsYearArchiveView.as_view(**info_dict)),
 
   url(r'^/?$', listing, dict(info_dict, paginate_by=6)),
 
]
www/conservancy/apps/news/views.py
Show inline comments
 
# from django.views.generic.list_detail import object_list
 
from django.views.generic import ListView
 
from django.template import RequestContext
 
from django.shortcuts import render_to_response
 
from django.shortcuts import render
 
from django.views.generic.dates import YearArchiveView, MonthArchiveView, DayArchiveView, DateDetailView
 
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
...
 
@@ -43,5 +42,5 @@ def listing(request, *args, **kwargs):
 
        news = paginator.page(paginator.num_pages)
 

	
 
    return render_to_response('news/pressrelease_list.html', {"news": news, "date_list" : date_list}, context_instance=RequestContext(request))
 
    return render(request, 'news/pressrelease_list.html', {"news": news, "date_list" : date_list})
 

	
 
class NewsYearArchiveView(YearArchiveView):
www/conservancy/apps/summit_registration/views.py
Show inline comments
 
from django.shortcuts import render_to_response
 
from django.template import RequestContext
 
from django.shortcuts import render
 
from django import forms
 
from django.template import RequestContext
 
from conervancy.apps.summit_registration.models import SummitRegistration
 

	
...
 
@@ -22,9 +20,7 @@ def register(request):
 
        if form.is_valid():
 
            form.save()
 
            return render_to_response('summit_registration/register_success.html',
 
                                      {'form': form.cleaned_data}, context_instance=RequestContext(request))
 
            return render(reqeust, 'summit_registration/register_success.html', {'form': form.cleaned_data})
 
    else:
 
        form = SummitForm()
 

	
 
    return render_to_response('summit_registration/register.html',
 
                              {'form': form}, context_instance=RequestContext(request))
 
    return render(request, 'summit_registration/register.html', {'form': form})
www/conservancy/apps/supporter/urls.py
Show inline comments
 
from django.conf.urls import patterns
 
from django.conf.urls import url
 
from conservancy.apps.supporter import views as supp_views
 
from conservancy.static import views as static_views
 

	
 
INDEX_VIEW = 'conservancy.apps.supporter.views.index'
 
pattern_pairs = [(r'^/?$', INDEX_VIEW)]
 
pattern_pairs.extend(
 
    (r'^{}(?:\.html|/|)$'.format(basename), INDEX_VIEW)
 
INDEX_VIEW = supp_views.index
 
urlpatterns = [url(r'^/?$', INDEX_VIEW)]
 
urlpatterns.extend(
 
    url(r'^{}(?:\.html|/|)$'.format(basename), INDEX_VIEW)
 
    for basename in ['index', '2015-supporter-appeal', '2016-supporter-appeal']
 
)
 
pattern_pairs.append((r'', 'conservancy.static.views.index'))
 

	
 
urlpatterns = patterns('', *pattern_pairs)
 
urlpatterns.append(url(r'', static_views.index))
www/conservancy/bsoup.py
Show inline comments
 
new file 100644
 
# -*- encoding: utf-8 -*-
 

	
 
import io
 
import re
 

	
 
import bs4
 
import bs4.element
 

	
 
class BeautifulSoup(bs4.BeautifulSoup):
 
    """A wrapper of the original BeautifulSoup class, with convenience methods added."""
 

	
 
    IMAGE_ATTRS = {
 
        'img': 'src',
 
        'video': 'poster',
 
    }
 
    NON_BODY_TEXT_TAGS = frozenset([
 
        'img',
 
        'video',
 
    ])
 
    SENTENCE_END = re.compile(r'[.?!]\s*\W*\s*$')
 

	
 
    def __init__(self, src, parser='html5lib'):
 
        # WARNING!  It seems like it would be ideal to use the 'lxml' parser
 
        # for speed, but that doesn't work in our web application.  On
 
        # Debian stretch, at least, using lxml causes the web server WSGI
 
        # application to go into an infinite loop.
 
        super(BeautifulSoup, self).__init__(src, parser)
 

	
 
    def _body_text(self, root):
 
        # "Body text" is all the strings under the root element, in order,
 
        # except:
 
        # * strings inside NON_BODY_TEXT_TAGS
 
        # * strings inside containers of NON_BODY_TEXT_TAGS.  A container is
 
        #   an element that has a NON_BODY_TEXT_TAGS element as its first child.
 
        #   For example, in <div> <video …> … </div>, none of the div's strings
 
        #   are included in the body text, because it's considered to be a
 
        #   <video> container, and any strings are probably a caption, fallback
 
        #   text, or other non-body text.
 
        started = False
 
        for child in root.children:
 
            child_type = type(child)
 
            if issubclass(child_type, bs4.element.Tag):
 
                if child.name in self.NON_BODY_TEXT_TAGS:
 
                    if not started:
 
                        break
 
                else:
 
                    for s in self._body_text(child):
 
                        yield s
 
            # It's not worth it to use issubclass here, because elements that
 
            # don't have body text like Comments and CDATA are subclasses of
 
            # NavigableString.
 
            elif child_type is bs4.element.NavigableString:
 
                if started:
 
                    yield child
 
                elif child.isspace():
 
                    pass
 
                else:
 
                    yield child
 
                    started = True
 

	
 
    def body_text(self):
 
        """Return an iterator of strings comprising this document's body text."""
 
        return self._body_text(self)
 

	
 
    def some_body_text(self, char_target=300):
 
        """Return an iterator of strings with some of this document's body text.
 

	
 
        This is the same as body_text, except after it yields a string that
 
        looks like the end of a sentence, it checks whether it has yielded
 
        at least `char_target` characters.  If so, the iterator stops.
 
        """
 
        # This implementation is likely to overshoot `char_target` a lot,
 
        # because it doesn't look inside the strings it yields, just at the
 
        # end of them.  We can implement something smarter later if needed.
 
        char_count = 0
 
        for s in self.body_text():
 
            yield s
 
            char_count += len(s)
 
            if (char_count > char_target) and self.SENTENCE_END.search(s):
 
                break
 

	
 
    @staticmethod
 
    def is_video_source(elem):
 
        try:
 
            return elem.name == 'source' and elem.parent.name == 'video'
 
        except AttributeError:
 
            return False
 

	
 
    def iter_attr(self, tag, attr_name, **kwargs):
 
        kwargs[attr_name] = True
 
        for elem in self.find_all(tag, **kwargs):
 
            yield elem[attr_name]
 

	
 
    def iter_image_urls(self):
 
        """Return an iterator of source URL strings of all images in this document.
 

	
 
        Images include <img> tags and <video> poster attributes.
 
        """
 
        for elem in self.find_all(list(self.IMAGE_ATTRS.keys())):
 
            try:
 
                yield elem[self.IMAGE_ATTRS[elem.name]]
 
            except KeyError:
 
                pass
 

	
 
    def iter_video_urls(self):
 
        """Return an iterator of source URL strings of all videos in this document."""
 
        return self.iter_attr(self.is_video_source, 'src')
 

	
 

	
 
class SoupModelMixin:
 
    """Mixin for models to parse HTML with BeautifulSoup.
 

	
 
    Classes that use this mixin must define `SOUP_ATTRS`, a list of strings
 
    that name attributes with HTML in them.  After that, all the public methods
 
    are usable.
 
    """
 

	
 
    SOUP_ATTRS = []
 

	
 
    def _get_soup(self):
 
        try:
 
            return self._soup
 
        except AttributeError:
 
            html = io.StringIO()
 
            for attr_name in self.SOUP_ATTRS:
 
                html.write(getattr(self, attr_name))
 
            html.seek(0)
 
            self._soup = BeautifulSoup(html)
 
            return self._soup
 

	
 
    def get_description(self):
 
        """Return a string with a brief excerpt of body text from the HTML."""
 
        return u''.join(self._get_soup().some_body_text())
 

	
 
    def get_image_urls(self):
 
        """Return an iterator of source URL strings of all images in the HTML.
 

	
 
        Images include <img> tags and <video> poster attributes.
 
        """
 
        return self._get_soup().iter_image_urls()
 

	
 
    def get_video_urls(self):
 
        """Return an iterator of source URL strings of all videos in the HTML."""
 
        return self._get_soup().iter_video_urls()
www/conservancy/feeds.py
Show inline comments
...
 
@@ -3,6 +3,5 @@ from django.utils.feedgenerator import Rss201rev2Feed
 
from conservancy.apps.news.models import PressRelease
 
from conservancy.apps.blog.models import Entry as BlogEntry
 
from django.template import RequestContext
 
from django.shortcuts import render_to_response
 
from django.shortcuts import render
 
from django.conf import settings
 
from datetime import datetime
...
 
@@ -256,3 +255,3 @@ def view(request):
 

	
 
    feeds = (PressReleaseFeed, BlogFeed, OmnibusFeed)
 
    return render_to_response("feeds.html", {'feeds': feeds}, context_instance=RequestContext(request))
 
    return render(request, "feeds.html", {'feeds': feeds})
www/conservancy/local_context_processors.py
Show inline comments
 
import conservancy.settings
 
from conservancy.apps.fundgoal.models import FundraisingGoal as FundraisingGoal
 

	
...
 
@@ -10,2 +11,10 @@ def fundgoal_lookup(fundraiser_sought):
 
def sitefundraiser(request):
 
    return {'sitefundgoal': fundgoal_lookup('supporterrun') }
 

	
 
if conservancy.settings.FORCE_CANONICAL_HOSTNAME:
 
    _HOST_URL_VAR = {'host_url': 'https://' + conservancy.settings.FORCE_CANONICAL_HOSTNAME}
 
    def host_url(request):
 
        return _HOST_URL_VAR
 
else:
 
    def host_url(request):
 
        return {'host_url': request.build_absolute_uri('/').rstrip('/')}
www/conservancy/settings.py
Show inline comments
...
 
@@ -28,4 +28,6 @@ FORCE_CANONICAL_HOSTNAME = False if DEBUG else 'sfconservancy.org'
 

	
 
ALLOWED_HOSTS = [ 'www.sfconservancy.org', 'aspen.sfconservancy.org', 'sfconservancy.org',  u'104.130.70.210' ]
 
if DEBUG:
 
    ALLOWED_HOSTS.append('localhost')
 

	
 
REDIRECT_TABLE = {
www/conservancy/sponsors.py
Show inline comments
 
from django.shortcuts import render_to_response
 
from django.template import RequestContext
 
from django.shortcuts import render
 
from conservancy.apps.supporters.models import Supporter as Supporter
 
from datetime import datetime, timedelta
...
 
@@ -20,3 +19,3 @@ def view(request):
 
        'anonymous_count' : anonymous_count
 
    }
 
    return render_to_response("sponsors.html", c, context_instance=RequestContext(request))
 
    return render(request, "sponsors.html", c)
www/conservancy/templates/blog/entry_detail.html
Show inline comments
 
{% extends "base_blog.html" %}
 

	
 
{% block head %}
 
{% include "opengraph_partial.html" with url=object.get_absolute_url title=object.headline description=object.get_description %}
 
{% include "opengraph_urllist_partial.html" with property='image' urls=object.get_image_urls fallback='/img/conservancy-logo.png' %}
 
{% include "opengraph_urllist_partial.html" with property='video' urls=object.get_video_urls %}
 
{% endblock %}
 

	
 
{% block subtitle %}{{ object.headline|striptags|safe }} - Conservancy Blog - {% endblock %}
 

	
www/conservancy/templates/news/pressrelease_detail.html
Show inline comments
 
{% extends "base_news.html" %}
 

	
 
{% block head %}
 
{% include "opengraph_partial.html" with url=object.get_absolute_url title=object.headline description=object.get_description %}
 
{% include "opengraph_urllist_partial.html" with property='image' urls=object.get_image_urls fallback='/img/conservancy-logo.png' %}
 
{% include "opengraph_urllist_partial.html" with property='video' urls=object.get_video_urls %}
 
{% endblock %}
 

	
 
{% block subtitle %}{{ object.headline|striptags|safe }} - {% endblock %}
 

	
www/conservancy/templates/opengraph_partial.html
Show inline comments
 
new file 100644
 
{% comment %}
 

	
 
Include this partial in a head section to include basic Open Graph metadata.
 
Pass a variable `NAME` to give a value for the `og:NAME` property.
 

	
 
These properties are only listed if you give a value for them:
 

	
 
* url: A URL string that includes at least an absolute path.  This partial
 
  will fill in a default scheme and host if needed.
 
* title: A string.  Tags are stripped, then the rest is assumed HTML-safe.
 
* description: A string.  Tags are stripped, then the rest is assumed
 
  HTML-safe.
 

	
 
These properties are always included.  You can override them but you
 
normally shouldn't need to:
 

	
 
* type: Default "website".
 
* locale: Default "en_US".
 
* site_name: Default "Software Freedom Conservancy"
 

	
 
{% endcomment %}
 

	
 
<meta property="og:type" content="{{ type|default:"website" }}">
 
<meta property="og:locale" content="{{ locale|default:"en_US" }}">
 
<meta property="og:site_name" content="{{ site_name|default:"Software Freedom Conservancy" }}">
 

	
 
{% if url %}
 
{% load fill_url %}
 
<meta property="og:url" content="{{ url|fill_url:host_url }}">
 
{% endif %}
 

	
 
{% if title %}
 
<meta property="og:title" content="{{ title|striptags|safe }}">
 
{% endif %}
 

	
 
{% if description %}
 
<meta property="og:description" content="{{ description|striptags|safe }}">
 
{% endif %}
www/conservancy/templates/opengraph_urllist_partial.html
Show inline comments
 
new file 100644
 
{% comment %}
 

	
 
Include this partial in a head section to include a series of URLs for a
 
given property, like og:image or og:video.
 

	
 
You must pass the following variables:
 

	
 
* property: A string with the name of the property, like 'image' or 'video'.
 
* urls: A sequence of URL strings.  Each should include at least an absolute
 
  path.  This partial will fill in a scheme and host if needed.
 

	
 
You may also pass:
 

	
 
* fallback: A URL string, following the same rules as in `urls`.  This URL
 
  will be used if `urls` is empty.
 

	
 
{% endcomment %}
 

	
 
{% load fill_url %}
 
{% for url in urls %}
 
<meta property="og:{{ property }}" content="{{ url|fill_url:host_url }}">
 
{% empty %}
 
{% if fallback %}
 
<meta property="og:{{ property }}" content="{{ fallback|fill_url:host_url }}">
 
{% endif %}
 
{% endfor %}
www/conservancy/urls.py
Show inline comments
...
 
@@ -18,74 +18,40 @@
 
# "AGPLv3".  If not, see <http://www.gnu.org/licenses/>.
 

	
 
from django.conf.urls import patterns, url, include
 
from django.contrib import admin
 
from django.conf.urls import url, include
 
from django.contrib import admin, admindocs
 

	
 
# import conservancy.settings
 
from django.conf import settings
 
from conservancy.feeds import BlogFeed, PressReleaseFeed, OmnibusFeed
 
# from django.views.static import serve
 
# from django.conf.urls.static import static
 
# from django.contrib.staticfiles.urls import staticfiles_urlpatterns
 
# import conservancy.static.overview.views
 

	
 
# handler404 = 'modpythoncustom.view404'
 
# handler401 = 'conservancy.static.views.handler401'
 
# handler403 = 'conservancy.static.views.handler403'
 
handler404 = 'conservancy.static.views.handler404'
 
# handler500 = 'conservancy.static.views.handler500'
 
from conservancy import feeds, frontpage, sponsors
 
import conservancy.apps.fundgoal.views as fundgoal_views
 
import conservancy.static.views as static_views
 

	
 
admin.autodiscover()
 

	
 
urlpatterns = patterns('',
 
    (r'^$', 'conservancy.frontpage.view'),
 
    (r'^sponsors$', 'conservancy.frontpage.view'),
 
    (r'^sponsors/$', 'conservancy.sponsors.view'),
 
    (r'^sponsors/index.html$', 'conservancy.sponsors.view'),
 
    (r'^admin/doc/', include('django.contrib.admindocs.urls')),
 
    (r'^admin/', admin.site.urls),
 
    (r'^feeds/blog/?$', BlogFeed()),
 
    (r'^feeds/news/?$', PressReleaseFeed()),
 
    (r'^feeds/omnibus/?$', OmnibusFeed()),
 
    (r'^feeds/?$', 'conservancy.feeds.view'),
 
    (r'^news(/|$)', include('conservancy.apps.news.urls')),
 
    (r'^blog(/|$)', include('conservancy.apps.blog.urls')),
 
urlpatterns = [
 
    url(r'^$', frontpage.view),
 
    url(r'^sponsors$', frontpage.view),
 
    url(r'^sponsors/$', sponsors.view),
 
    url(r'^sponsors/index.html$', sponsors.view),
 
    url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
 
    url(r'^admin/', admin.site.urls),
 
    url(r'^feeds/blog/?$', feeds.BlogFeed()),
 
    url(r'^feeds/news/?$', feeds.PressReleaseFeed()),
 
    url(r'^feeds/omnibus/?$', feeds.OmnibusFeed()),
 
    url(r'^feeds/?$', feeds.view),
 
    url(r'^news(/|$)', include('conservancy.apps.news.urls')),
 
    url(r'^blog(/|$)', include('conservancy.apps.blog.urls')),
 
    # formerly static templated things... (dirs with templates)
 
    (r'^error/(40[134]|500)(?:/index\.html|/|)$', 'conservancy.static.views.handler'),
 
    (r'^error', 'conservancy.static.views.index'),
 
    (r'^about', 'conservancy.static.views.index'),
 
    (r'^donate', 'conservancy.static.views.index'),
 
    (r'^copyleft-compliance', 'conservancy.static.views.index',
 
    url(r'^error/(40[134]|500)(?:/index\.html|/|)$', static_views.handler),
 
    url(r'^error', static_views.index),
 
    url(r'^about', static_views.index),
 
    url(r'^donate', static_views.index),
 
    url(r'^copyleft-compliance', static_views.index,
 
                           {'fundraiser_sought' : 'vmware-match-0'}),
 
    (r'^projects', 'conservancy.static.views.index'),
 
    (r'^npoacct', 'conservancy.static.views.index',
 
    url(r'^projects', static_views.index),
 
    url(r'^npoacct', static_views.index,
 
                  {'fundraiser_sought' : 'npoacct'}),
 
    (r'^contractpatch', include('conservancy.apps.contractpatch.urls')),
 
    (r'^overview', 'conservancy.static.views.index'),
 
    (r'^privacy-policy', 'conservancy.static.views.index'),
 
    (r'^supporter', include('conservancy.apps.supporter.urls')),
 
    (r'^fundraiser_data', 'conservancy.apps.fundgoal.views.view'),
 
)
 

	
 
# urlpatterns += url(regex  = r'^%s(?P<path>.*)$' % conservancy.settings.STATIC_URL[1:],
 
# urlpatterns += url(regex  = r'^/overview',
 
#                    view   = 'django.views.static.serve',
 
#                    kwargs = {'document_root': conservancy.settings.STATIC_ROOT,
 
#                              'show_indexes' : True})
 
# urlpatterns += (r'^(?P<path>.*)$', 'django.views.static.serve', 
 
# urlpatterns += (r'^overview/$', 'django.views.static.serve', 
 
#                 {'document_root': conservancy.settings.STATIC_ROOT,
 
#                  'show_indexes' : True})
 

	
 
# https://docs.djangoproject.com/en/1.7/howto/static-files/
 
#  + static(conservancy.settings.STATIC_URL, document_root=conservancy.settings.STATIC_ROOT)
 

	
 
# urlpatterns += staticfiles_urlpatterns()
 

	
 
# urlpatterns += static(settings.STATIC_URL, view='django.contrib.staticfiles.views.serve',
 
# urlpatterns += static('/', view='django.contrib.staticfiles.views.serve',
 
#                       document_root=settings.STATIC_ROOT,
 
#                       show_indexes=True)
 

	
 

	
 

	
 

	
 
    url(r'^contractpatch', include('conservancy.apps.contractpatch.urls')),
 
    url(r'^overview', static_views.index),
 
    url(r'^privacy-policy', static_views.index),
 
    url(r'^supporter', include('conservancy.apps.supporter.urls')),
 
    url(r'^fundraiser_data', fundgoal_views.view),
 
]
0 comments (0 inline, 0 general)