Changeset - 07faf5cebca9
www/conservancy/__init__.py
Show inline comments
 
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):
 
        if params_hash_key is None:
 
            self.given_hash = given_hash_or_params
 
        else:
 
            self.given_hash = given_hash_or_params.get(params_hash_key)
 
        seed = getattr(settings, 'CONSERVANCY_SECRET_KEY', '')
 
        self.hasher = hashlib.sha256(seed)
 
        if isinstance(self.given_hash, basestring):
 
            self.hash_type = type(self.given_hash)
 
        else:
 
            self.hash_type = type(self.hasher.hexdigest())
 
        self.valid = None
 
        if not (self.given_hash and seed):
 
            self.fail()
 

	
 
    def __enter__(self):
 
        self.valid = self.valid and None
 
        return self
 

	
 
    def __exit__(self, exc_type, exc_value, exc_tb):
 
        if exc_type is None:
 
            self.check()
 
        else:
 
            self.fail()
 

	
 
    def validate(self, data):
 
        self.valid = self.valid and None
 
        self.hasher.update(data)
 

	
 
    def check(self):
 
        if self.valid or (self.valid is None):
 
            self.valid = self.hash_type(self.hasher.hexdigest()) == self.given_hash
 
        return self.valid
 

	
 
    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
 

	
 
class EntryTag(models.Model):
 
    """Tagging for blog entries"""
 

	
 
    label = models.CharField(max_length=100)
 
    slug = models.SlugField()
 

	
 
    class Meta:
 
        db_table = 'techblog_entrytag' # legacy
 

	
 
    def __unicode__(self):
 
        return self.label
 

	
 
    def get_absolute_url(self):
 
        return u"/blog/?tag=%s" % self.slug
 

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

	
 
    headline = models.CharField(max_length=200)
 
    slug = models.SlugField(unique_for_date='pub_date')
 
    summary = models.TextField(help_text="Use raw HTML.  Unlike in the press release model, this summary is not included at the beginning of the body when the entry is displayed.")
 
    body = models.TextField(help_text="Use raw HTML.  Include the full body of the post.")
 
    pub_date = models.DateTimeField()
 
    author = models.ForeignKey(Person)
 
    tags = models.ManyToManyField(EntryTag, null=True, blank=True)
 

	
 
    date_created = models.DateTimeField(auto_now_add=True)
 
    date_last_modified = models.DateTimeField(auto_now=True)
 

	
 
    class Meta:
 
        db_table = 'techblog_entries' # legacy
 
        verbose_name_plural = 'entries'
 
        ordering = ('-pub_date',)
 
        get_latest_by = 'pub_date'
 

	
 
    SOUP_ATTRS = ['body']
 

	
 
    def __unicode__(self):
 
        return self.headline
 

	
 
    def get_absolute_url(self):
 
        return (u"/blog/%s/%s/"
 
                % (self.pub_date.strftime("%Y/%b/%d").lower(),
 
                   self.slug))
 

	
 
    def is_recent(self):
 
        return self.pub_date > (datetime.now() - timedelta(days=30))
 
        # question: does datetime.now() do a syscall each time is it called?
 

	
 
    # Ping google blogs and technorati.  Taken from
 
    # http://blog.foozia.com/blog/2007/apr/21/ping-technorati-your-django-blog-using-xml-rpc/
 
    def save(self):
 
        if settings.CONSERVANCY_DEVEL or True: # "or True" means it is disabled always
 
            super(Entry, self).save()
 
            return
 

	
 
        blog_name = 'Software Freedom Law Center Blog'
 
        blog_url =  'http://www.softwarefreedom.org/blog/'
 
        post_url = ('http://www.softwarefreedom.org'
 
                    + self.get_absolute_url())
 

	
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 = {}
 

	
 
info_dict = {
 
    'queryset': Entry.objects.all(),
 
    'date_field': 'pub_date',
 
    'extra_context': extra_context,
 
}
 

	
 
# 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
 

	
 
def all_tags_by_use_amount():
 
    """Returns all tags with an added 'cnt' attribute (how many times used)
 

	
 
    Also sorts the tags so most-used tags appear first.
 
    """
 

	
 
    # tally use amount
 
    retval = []
 
    current = None
 
    for obj in EntryTag.objects.filter(entry__pub_date__lte=datetime.now(),
 
                                       entry__isnull=False).order_by('label'):
 
        if current is not None and obj.id == current.id:
 
            current.cnt += 1
 
        else:
 
            if current is not None:
 
                retval.append(current)
 
            current = obj
 
            current.cnt = 1
 
    if current is not None:
 
        retval.append(current)
 

	
www/conservancy/apps/blog/views.py
Show inline comments
 
from conservancy.apps.blog.models import Entry, EntryTag # relative import
 
# from django.views.generic.list_detail import object_list
 
from django.views.generic import ListView
 
from django.views.generic.dates import YearArchiveView, MonthArchiveView, DayArchiveView, DateDetailView
 
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
 

	
 
def OR_filter(field_name, objs):
 
    from django.db.models import Q
 
    return reduce(lambda x, y: x | y,
 
                  [Q(**{field_name: x.id}) for x in objs])
 

	
 
def last_name(person):
 
    return person.formal_name.rpartition(' ')[2]
 

	
 
def custom_index(request, queryset, *args, **kwargs):
 
    """Blog list view that allows scrolling and also shows an index by
 
    year.
 
    """
 

	
 
    extra_context = kwargs.get('extra_context', {}).copy()
 
    date_field = kwargs['date_field']
 

	
 
    if not kwargs.get('allow_future', False):
 
        queryset = queryset.filter(**{'%s__lte' % date_field: datetime.now()})
 

	
 
    authors = []
 
    if 'author' in request.GET:
 
        authors = [get_object_or_404(Person, username=author)
...
 
@@ -44,88 +43,87 @@ def custom_index(request, queryset, *args, **kwargs):
 
    if authors or tags:
 
        query_string = '&'.join(['author=%s' % a.username for a in authors]
 
                                + ['tag=%s' % t.slug for t in tags])
 
        extra_context['query_string'] = query_string
 

	
 
    else:
 
        date_list = queryset.dates(date_field, 'year')
 
        extra_context['date_list'] = date_list
 

	
 
    paginate_by = kwargs.get('paginate_by', 6)  # Show 6 news items per page, by default
 
    paginator = Paginator(queryset, paginate_by)
 
    page = request.GET.get('page')
 

	
 
    try:
 
        blog_entries = paginator.page(page)
 
    except PageNotAnInteger:
 
        # If page is not an integer, deliver first page.
 
        blog_entries = paginator.page(1)
 
    except EmptyPage:
 
        # If page is out of range (e.g. 9999), deliver last page of results.
 
        blog_entries = paginator.page(paginator.num_pages)
 

	
 
    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):
 
    """Redirect from the old 'techblog' to the new blog
 
    """
 

	
 
    path = request.path[len('/technology'):]
 
    if path == '/blog/':
 
        path += "?author=bkuhn"
 

	
 
    return relative_redirect(request, path)
 

	
 
def query(request):
 
    """Page to query the blog based on authors and tags
 
    """
 

	
 
    if request.GET:
 
        d = request.GET.copy()
 
        if 'authors' in d.getlist('all'):
 
            d.setlist('author', []) # remove author queries
 
        if 'tags' in d.getlist('all'):
 
            d.setlist('tag', []) # remove tag queries
 
        d.setlist('all', []) # remove "all" from the query string
 

	
 
        base_url = '/blog/'
 
        if 'rss' in d:
 
            base_url = '/feeds/blog/'
 
            d.setlist('rss', []) # remove it
 

	
 
        query_string = d.urlencode()
 

	
 
        return relative_redirect(request, '%s%s%s' % (base_url, '?' if query_string else '', query_string))
 

	
 
    else:
 
        authors = sorted(Person.objects.filter(currently_employed=True,
 
                                               entry__isnull=False).distinct(),
 
                         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):
 
    from django import http
 
    from django.conf import settings
 

	
 
    host = request.get_host()
 
    if settings.FORCE_CANONICAL_HOSTNAME:
 
        host = settings.FORCE_CANONICAL_HOSTNAME
 

	
 
    url = "%s://%s%s" % (request.is_secure() and 'https' or 'http', host, path)
 
    return http.HttpResponseRedirect(url)
 

	
 
class BlogYearArchiveView(YearArchiveView):
 
    make_object_list = True
 
    allow_future = True
 
    extra_context = {}
 
    
 
    def get_context_data(self, **kwargs):
 
        context = super(BlogYearArchiveView, self).get_context_data(**kwargs)
 
        context.update(self.extra_context)
 
        return context
 

	
 
class BlogMonthArchiveView(MonthArchiveView):
 
    allow_future = True
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
 
from django.forms import ModelForm
 

	
 
def subscribe(request):
 
    """Mailing list subscription form
 
    """
 

	
 
    class ContactEntryForm(ModelForm):
 
        class Meta:
 
            model = ContactEntry
 

	
 
    ContactEntryForm.base_fields['subscribe_conservancy'].label = 'Receive Software Freedom Conservancy updates'
 

	
 
    if request.method == 'POST':
 
        form = ContactEntryForm(request.POST)
 
        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
 
from django.core.exceptions import ObjectDoesNotExist
 
from conservancy.apps.events.models import Event
 
# for debugging...
 
from django.http import HttpResponse
 

	
 
def event_detail(request, year, slug, queryset, **kwargs):
 
    """This view shows event detail.
 

	
 
    Nothing special, but it is necessary because
 
    django.views.generic.date_based.object_detail only works with
 
    slugs that are unique and specified by day, but we make slugs
 
    unique by year.
 
    """
 

	
 
    try:
 
        event = queryset.get(date__year=year, slug__exact=slug)
 
    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):
 
    """Scrollable index of future and past events, with date index.
 
    """
 

	
 
    future_events = None
 
    if not request.GET.has_key("page"):
 
        future_events = Event.future.all().order_by("date")
 

	
 
    date_list = queryset.dates(kwargs['date_field'], 'year')
 

	
 
    kwargs = dict(kwargs, extra_context={'date_list': date_list,
 
                                         'future_events': future_events})
 
    del kwargs['date_field']
 
    del kwargs['allow_future']
 

	
 
    # return object_list(request, queryset, *args, **kwargs)
 
    return HttpResponse("FIXME: events must be updated like blog and news.")
 

	
 
def future_event_ics(request, queryset, *args, **kwargs):
 
    """ICS calendar view of future events
 

	
 
    This view just renders information into a template that looks like
 
    an ics file.  If in the future we want a 'real' implementation of
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
 
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"""
 

	
 
    headline = models.CharField(max_length=300)
 
    subhead = models.CharField(max_length=300, blank=True)
 
    slug = models.SlugField(unique_for_date="pub_date",
 
                            help_text=("automatically built from headline"))
 
    summary = models.TextField(help_text="First paragraph (raw HTML)")
 
    body = models.TextField(help_text="Remainder of post (raw HTML)",
 
                            blank=True)
 
    pub_date = models.DateTimeField("date [to be] published")
 
    sites = models.ManyToManyField(Site)
 

	
 
    date_last_modified = models.DateTimeField(auto_now=True)
 

	
 
    class Meta:
 
        ordering = ("-pub_date",)
 
        get_latest_by = "pub_date"
 

	
 
    SOUP_ATTRS = ['summary', 'body']
 

	
 
    def __unicode__(self):
 
        return self.headline
 

	
 
    def get_absolute_url(self):
 
        return u"/news/%s/%s/" % (self.pub_date.strftime("%Y/%b/%d").lower(),
 
                                  self.slug)
 

	
 
    def is_recent(self):
 
        return self.pub_date > (datetime.now() - timedelta(days=5))
 
        # question: does datetime.now() do a syscall each time is it called?
 

	
 
    def is_in_past_month(self):
 
        # This function is deprecated.  Use the date_within template
 
        # filter instead (example in conservancy/templates/frontpage.html)
 
        return self.pub_date > (datetime.now() - timedelta(days=30))
 

	
 
    def save(self):
 
        if settings.CONSERVANCY_DEVEL or True:
 
            super(PressRelease, self).save()
 
            return
 

	
 
        blog_name = 'Software Freedom Law Center News'
 
        blog_url =  'http://www.softwarefreedom.org/news/'
 
        post_url = ('http://www.softwarefreedom.org'
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
 
# Copyright 2005-2008, James Garrison
 
# Copyright 2010, Bradley M. Kuhn
 

	
 
# This software's license gives you freedom; you can copy, convey,
 
# propagate, redistribute, modify and/or redistribute modified versions of
 
# this program under the terms of the GNU Affero General Public License
 
# (AGPL) as published by the Free Software Foundation (FSF), either
 
# version 3 of the License, or (at your option) any later version of the
 
# AGPL published by the FSF.
 
#
 
# This program is distributed in the hope that it will be useful, but
 
# WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero
 
# General Public License for more details.
 
#
 
# You should have received a copy of the GNU Affero General Public License
 
# along with this program in a file in the toplevel directory called
 
# "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 = {
 
    'queryset': PressRelease.objects.all().filter(sites__id__exact=settings.SITE_ID),
 
    'date_field': 'pub_date',
 
}
 

	
 
external_article_dict = {
 
    'articles': ExternalArticle.objects.all()
 
}
 

	
 
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
 
from conservancy.apps.news.models import ExternalArticle
 
from conservancy.apps.news.models import PressRelease
 
from conservancy.apps.events.models import Event
 
from datetime import datetime
 
# for debugging...
 
from django.http import HttpResponse
 

	
 

	
 
class NewsListView(ListView):
 
    extra_context = {}
 
    def get_context_data(self, **kwargs):
 
        context = super(NewsListView, self).get_context_data(**kwargs)
 
        # context['key'] = 'value'
 
        context.update(self.extra_context)
 
        return context
 
                                    
 
def listing(request, *args, **kwargs):
 
    news_queryset = PressRelease.objects.all()
 

	
 
#    if (not kwargs.has_key('allow_future')) or not kwargs['allow_future']:
 
    news_queryset = news_queryset.filter(**{'%s__lte' % kwargs['date_field']:
 
                          datetime.now()})
 

	
 
    date_list = news_queryset.dates(kwargs['date_field'], 'year')
 

	
 
    paginate_by = kwargs.get('paginate_by', 6)  # Show 6 news items per page, by default
 
    paginator = Paginator(news_queryset, paginate_by)
 

	
 
    page = request.GET.get('page')
 
    try:
 
        news = paginator.page(page)
 
    except PageNotAnInteger:
 
        # If page is not an integer, deliver first page.
 
        news = paginator.page(1)
 
    except EmptyPage:
 
        # If page is out of range (e.g. 9999), deliver last page of results.
 
        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):
 
    # queryset = Article.objects.all()
 
    # date_field = "pub_date"
 
    make_object_list = True
 
    allow_future = True
 

	
 
# def archive_year(request, **kwargs):
 
#     callable = NewsYearArchiveView.as_view(**kwargs)
 
#     return callable(request)
 

	
 
class NewsMonthArchiveView(MonthArchiveView):
 
    allow_future = True
 

	
 
# def archive_month(request, **kwargs):
 
#     # return HttpResponse("archive_month")
 
#     callable = NewsMonthArchiveView.as_view(**kwargs)
 
#     return callable(request)
 

	
 
class NewsDayArchiveView(DayArchiveView):
 
    allow_future = True
 

	
 
# def archive_day(request, **kwargs):
 
#     # return HttpResponse("archive_day")
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
 

	
 
def register(request):
 
    """Summit registration form view
 
    """
 

	
 
    class SummitForm(ModelForm):
 
        class Meta:
 
            model = SummitRegistration
 

	
 
    SummitForm.base_fields['email'].label = 'Email address'
 
    SummitForm.base_fields['phone'].label = 'Phone number'
 
    SummitForm.base_fields['address'].label = 'Mailing address'
 
    SummitForm.base_fields['cle_credit'].label = 'Attending for CLE credit?'
 

	
 
    if request.method == 'POST':
 
        form = SummitForm(request.POST)
 
        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
 
from django.contrib.syndication.views import Feed
 
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
 

	
 
import itertools
 
import operator
 

	
 
class ConservancyFeedBase(Feed):
 
    def copyright_holder(self): return "Software Freedom Conservancy"
 

	
 
    def license_no_html(self): return "Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License."
 

	
 
    def item_copyright(self, item):
 
        year = 2008
 
        for attr in ('pub_date', 'date_created', 'date_last_modified'):
 
            if hasattr(item, attr):
 
                if hasattr(getattr(item, attr), 'year'):
 
                    year = getattr(getattr(item, attr), 'year')
 
                    break
 
        return 'Copyright (C) %d, %s.  %s' % (year, self.copyright_holder(), self.license_no_html())
 

	
 
    def item_extra_kwargs(self, item):
 
        year = 2008
 
        for attr in ('pub_date', 'date_created', 'date_last_modified'):
 
            if hasattr(item, attr):
...
 
@@ -234,25 +233,25 @@ class BlogFeed(ConservancyFeedBase):
 
        def OR_filter(field_name, subfield_name, objs):
 
            from django.db.models import Q
 
            return reduce(lambda x, y: x | y,
 
                          [Q(**{'%s__%s' % (field_name, subfield_name): x})
 
                           for x in objs])
 

	
 
        queryset = BlogEntry.objects.filter(pub_date__lte=datetime.now())
 

	
 
        if 'author' in GET:
 
            authors = GET.getlist('author')
 
            queryset = queryset.filter(OR_filter('author', 'username', authors))
 

	
 
        if 'tag' in GET:
 
            tags = GET.getlist('tag')
 
            queryset = queryset.filter(OR_filter('tags', 'slug', tags))
 

	
 
        return queryset.order_by('-pub_date')[:10]
 

	
 

	
 
def view(request):
 
    """Listing of all available feeds
 
    """
 

	
 
    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
 

	
 
def fundgoal_lookup(fundraiser_sought):
 
    try:
 
        return FundraisingGoal.objects.get(fundraiser_code_name=fundraiser_sought)
 
    except FundraisingGoal.DoesNotExist:
 
        # we have no object!  do something
 
        return None
 

	
 
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
...
 
@@ -6,40 +6,42 @@
 
# this program under the terms of the GNU Affero General Public License
 
# (AGPL) as published by the Free Software Foundation (FSF), either
 
# version 3 of the License, or (at your option) any later version of the
 
# AGPL published by the FSF.
 
#
 
# This program is distributed in the hope that it will be useful, but
 
# WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero
 
# General Public License for more details.
 
#
 
# You should have received a copy of the GNU Affero General Public License
 
# along with this program in a file in the toplevel directory called
 
# "AGPLv3".  If not, see <http://www.gnu.org/licenses/>.
 

	
 
import os.path
 

	
 
from djangocommonsettings import *
 

	
 
SITE_ID = 2
 
ROOT_URLCONF = 'conservancy.urls'
 

	
 
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.sf-conservancy.org': 'sfconservancy.org',
 
}
 

	
 
_root_dir = os.path.abspath(os.path.dirname(__file__))
 
TEMPLATE_DIRS = (
 
    os.path.join(_root_dir, 'templates'),
 
    os.path.join(_root_dir, 'static'),
 
)
 
del _root_dir
 

	
 
# try:
 
#     from djangodebug import conservancy_hostname as FORCE_CANONICAL_HOSTNAME
 
# except:
 
#     pass
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
 

	
 
def view(request):
 
    """Conservancy Sponsors Page view
 

	
 
    Performs object queries necessary to render the sponsors page.
 
    """
 

	
 
    supporters = Supporter.objects.all().filter(display_until_date__gte=datetime.now())
 
    supporters_count = len(supporters)
 
    anonymous_count  = len(supporters.filter(display_name = 'Anonymous'))
 
    supporters = supporters.exclude(display_name = 'Anonymous').order_by('ledger_entity_id')
 

	
 
    c = {
 
        'supporters' : supporters,
 
        'supporters_count' : supporters_count,
 
        '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 %}
 

	
 
{% block content %}
 

	
 
{% include "blog/entry_partial.html" with entry=object htag="h2" only %}
 

	
 
<p class="blog-comments">Please email any comments on this entry to
 
  <a href="mailto:info@sfconservancy.org">info@sfconservancy.org</a>.</p>
 

	
 
<p><span class="continued"><a href="/blog/">Other Conservancy Blog entries&hellip;</a></span></p>
 

	
 
{% 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 %}
 

	
 
{% block content %}
 

	
 
<div id="mainContent">
 
{% include "news/pressrelease_partial.html" with pressr=object htag="h2" only %}
 
</div>
 
{% 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
 
# Copyright 2005-2008, James Garrison
 
# Copyright 2010, 2012 Bradley M. Kuhn
 

	
 
# This software's license gives you freedom; you can copy, convey,
 
# propagate, redistribute, modify and/or redistribute modified versions of
 
# this program under the terms of the GNU Affero General Public License
 
# (AGPL) as published by the Free Software Foundation (FSF), either
 
# version 3 of the License, or (at your option) any later version of the
 
# AGPL published by the FSF.
 
#
 
# This program is distributed in the hope that it will be useful, but
 
# WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero
 
# General Public License for more details.
 
#
 
# You should have received a copy of the GNU Affero General Public License
 
# along with this program in a file in the toplevel directory called
 
# "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)