Changeset - 31e51a774223
[Not reviewed]
www/conservancy/__init__.py
Show inline comments
 
from builtins import object
 
import hashlib
 

	
 
from django.conf import settings
 
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', '').encode('utf-8')
 
        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()
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:
 
    class Meta(object):
 
        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, 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:
 
    class Meta(object):
 
        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()
www/conservancy/apps/contacts/models.py
Show inline comments
 
from builtins import object
 
from django.db import models
 

	
 
class ContactEntry(models.Model):
 
    """Conservancy contact system
 

	
 
    Hopefully this will be deprecated soon"""
 

	
 
    email = models.EmailField() # should make it unique, but we really cannot
 
    subscribe_conservancy = models.BooleanField(default=False)
 

	
 
    class Meta:
 
    class Meta(object):
 
        ordering = ('email',)
 

	
www/conservancy/apps/contacts/views.py
Show inline comments
 
from builtins import object
 
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:
 
        class Meta(object):
 
            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(request, 'contacts/subscribe_success.html', {'form': form.cleaned_data})
 
    else:
 
        form = ContactEntryForm()
 

	
 
    return render(request, 'contacts/subscribe.html', {'form': form})
www/conservancy/apps/events/models.py
Show inline comments
 
from builtins import object
 
from django.db import models
 
from conservancy.apps.staff.models import Person
 
from conservancy.apps.worldmap.models import EarthLocation
 
from datetime import datetime, timedelta
 

	
 
class EventTag(models.Model):
 
    """Tagging for events
 

	
 
    (currently unused)
 
    """
 

	
 
    label = models.CharField(max_length=100)
 

	
 
    date_created = models.DateField(auto_now_add=True)
 

	
 
    def __unicode__(self):
 
        return self.label
 

	
 
class PastEventManager(models.Manager):
 
    """Returns all past events"""
 

	
 
    def get_queryset(self):
 
        return super(PastEventManager, self).get_queryset().filter(date__lt=datetime.today())
 

	
 
class FutureEventManager(models.Manager):
 
    """Returns all future events"""
 

	
 
    def get_queryset(self):
 
        return super(FutureEventManager, self).get_queryset().filter(date__gte=datetime.today())
 

	
 
class Event(models.Model):
 
    """Model for Conservancy staff member events (presentations, etc)"""
 

	
 
    title = models.CharField(max_length=400)
 
    date = models.DateField()
 
    date_tentative = models.BooleanField(default=False)
 
    datetime = models.CharField("Date and Time", max_length=300, blank=True)
 
    slug = models.SlugField(unique_for_year='date')
 
    description = models.TextField(blank=True)
 
    people = models.ManyToManyField(Person, null=True, blank=True)
 
    location = models.CharField(max_length=1000)
 
    earth_location = models.ForeignKey(EarthLocation, null=True, blank=True,
 
                                       help_text="Label will not be displayed")
 
    tags = models.ManyToManyField(EventTag, null=True, blank=True)
 

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

	
 
    class Meta:
 
    class Meta(object):
 
        ordering = ("-date",)
 

	
 
    def __unicode__(self):
 
        return u"%s (%s)" % (self.title, self.date)
 

	
 
    def get_absolute_url(self):
 
        return u"/events/%s/%s/" % (self.date.strftime("%Y"), self.slug)
 

	
 
    def day_after(self):
 
        return self.date + timedelta(days=1)
 

	
 
    # for aggregate feed
 
    pub_date = property(lambda self: self.date_created)
 

	
 
    objects = models.Manager()
 
    past = PastEventManager()
 
    future = FutureEventManager()
 

	
 
class EventMedia(models.Model):
 
    """Media from an event
 

	
 
    includes transcripts, audio, and video pieces
 
    """
 

	
 
    event = models.ForeignKey(Event)
 
    format = models.CharField(max_length=1,
 
                              choices=(('T', 'Transcript'),
 
                                       ('A', 'Audio'),
 
                                       ('V', 'Video')))
 
    local = models.CharField(max_length=300, blank=True,
 
                             help_text="Local filename of the resource.  File should be uploaded into the static directory that corresponds to the event.")
 
    # verify_exists removed https://docs.djangoproject.com/en/1.7/releases/1.4/
 
    remote = models.URLField(blank=True,
 
                             help_text="Remote URL of the resource.  Required if 'local' is not given.")
 
    novel = models.BooleanField(help_text="Is it a new piece of media or another form of an old one?  If it is new it will be included in the event-media RSS feed and shown on the front page for a bit.", default=False)
 

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

	
 
    class Meta:
 
    class Meta(object):
 
        verbose_name_plural = 'event media'
 

	
 
    def __unicode__(self):
 
        return u"%s media: %s" % (self.event, self.format)
 

	
www/conservancy/apps/fundgoal/models.py
Show inline comments
 
from builtins import object
 
import random
 

	
 
from django.db import models
 

	
 
class FundraisingGoal(models.Model):
 
    """Conservancy fundraiser Goal"""
 

	
 
    fundraiser_code_name = models.CharField(max_length=200, blank=False, unique=True)
 
    fundraiser_goal_amount = models.DecimalField(max_digits=10, decimal_places=2)
 
    fundraiser_so_far_amount = models.DecimalField(max_digits=10, decimal_places=2)
 
    fundraiser_donation_count = models.IntegerField()
 
    fundraiser_donation_count_disclose_threshold = models.IntegerField()
 
    fundraiser_endtime = models.DateTimeField(null=True)
 

	
 
    def __unicode__(self):
 
        return self.fundraiser_code_name
 

	
 
    def percentage_there(self):
 
        return (self.fundraiser_so_far_amount / self.fundraiser_goal_amount ) * 100
 
    
 
    class Meta:
 
    class Meta(object):
 
        ordering = ('fundraiser_code_name',)
 

	
 
    def providers(self):
 
        return GoalProvider.objects.filter(fundraising_goal=self)
 

	
 
    def random_providers(self, k=None):
 
        providers = self.providers()
 
        if not providers.exists():
 
            return None
 
        elif k is None:
 
            return random.choice(providers)
 
        else:
 
            return random.sample(providers, k)
 

	
 

	
 
class GoalProvider(models.Model):
 
    fundraising_goal = models.ForeignKey(
 
        'FundraisingGoal',
 
        on_delete=models.CASCADE,
 
    )
 
    provider_name = models.CharField(max_length=512)
 

	
 
    def __unicode__(self):
 
        return self.provider_name
www/conservancy/apps/news/models.py
Show inline comments
 
from builtins import object
 
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, 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:
 
    class Meta(object):
 
        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()
www/conservancy/apps/staff/models.py
Show inline comments
 
from builtins import object
 
from django.db import models
 

	
 
class Person(models.Model):
 
    """Staff members
 

	
 
    Referenced from other models (blog, events, etc)
 
    """
 

	
 
    username = models.CharField(max_length=20)
 
    formal_name = models.CharField(max_length=200)
 
    casual_name = models.CharField(max_length=200)
 
#    title = models.CharField(max_length=200, blank=True)
 
#    biography = models.TextField(blank=True)
 
#    phone = models.CharField(max_length=30, blank=True)
 
#    gpg_key = models.TextField(blank=True)
 
#    gpg_fingerprint = models.CharField(max_length=100, blank=True)
 
    currently_employed = models.BooleanField(default=True)
 

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

	
 
    class Meta:
 
    class Meta(object):
 
        verbose_name_plural = 'people'
 

	
 
    def __unicode__(self):
 
        return self.username
 

	
 
    def biography_url(self):
 
        return u"/about/#%s" % self.username
 

	
www/conservancy/apps/summit_registration/models.py
Show inline comments
 
from builtins import object
 
from django.db import models
 

	
 
class SummitRegistration(models.Model):
 
    """Form fields for summit registrants"""
 

	
 
    name = models.CharField(max_length=300)
 
    affiliation = models.CharField(max_length=700, blank=True)
 
    address = models.TextField(blank=True)
 
    email = models.EmailField(blank=True)
 
    phone = models.CharField(max_length=100, blank=True)
 
    date_created = models.DateField(auto_now_add=True)
 
    cle_credit = models.BooleanField(default=True)
 

	
 
    class Meta:
 
    class Meta(object):
 
        ordering = ('name',)
 

	
www/conservancy/apps/summit_registration/views.py
Show inline comments
 
from builtins import object
 
from django.shortcuts import render
 
from django import forms
 
from conervancy.apps.summit_registration.models import SummitRegistration
 

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

	
 
    class SummitForm(ModelForm):
 
        class Meta:
 
        class Meta(object):
 
            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(reqeust, 'summit_registration/register_success.html', {'form': form.cleaned_data})
 
    else:
 
        form = SummitForm()
 

	
 
    return render(request, 'summit_registration/register.html', {'form': form})
www/conservancy/apps/supporters/models.py
Show inline comments
 
from builtins import object
 
from django.db import models
 

	
 
class Supporter(models.Model):
 
    """Conservancy Supporter listing"""
 

	
 
    display_name = models.CharField(max_length=200, blank=False)
 
    display_until_date = models.DateTimeField("date until which this supporter name is displayed")
 
    ledger_entity_id = models.CharField(max_length=200, blank=False)
 

	
 
    def test(self):
 
        return "TESTING"
 
    def __unicode__(self):
 
        return self.display_name
 

	
 
    class Meta:
 
    class Meta(object):
 
        ordering = ('ledger_entity_id',)
www/conservancy/apps/worldmap/models.py
Show inline comments
 
from builtins import object
 
from django.db import models
 

	
 
class EarthLocation(models.Model):
 
    """Represents latitude and longitude, with a label"""
 

	
 
    label = models.CharField(max_length=300, unique=True)
 
    latitude = models.DecimalField(max_digits=9, decimal_places=6)
 
    longitude = models.DecimalField(max_digits=9, decimal_places=6)
 

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

	
 
    class Meta:
 
    class Meta(object):
 
        unique_together = (("latitude", "longitude"),)
 

	
 
    def __unicode__(self):
 
        return self.label
 

	
 
    def google_maps_link(self):
 
        return ("http://maps.google.com/maps?ll=%s,%s&z=15"
 
                % (self.latitude, self.longitude))
 

	
 
    default_map_link = google_maps_link
 

	
 
    def html_map_link(self): # for Admin, fixme: fix_ampersands
 
        return '<a href="%s">map link</a>' % self.default_map_link()
 
    html_map_link.allow_tags = True
 

	
www/conservancy/bsoup.py
Show inline comments
 
# -*- encoding: utf-8 -*-
 

	
 
from builtins import object
 
import io
 
import itertools
 
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
...
 
@@ -84,49 +85,49 @@ class BeautifulSoup(bs4.BeautifulSoup):
 
    def is_video_source(elem):
 
        try:
 
            return elem.name == 'source' and elem.parent.name == 'video'
 
        except AttributeError:
 
            return False
 

	
 
    def iter_images(self):
 
        """Return an iterator of all image elements in this document.
 

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

	
 
    def iter_videos(self):
 
        """Return an iterator of all video source elements in this document."""
 
        return self.find_all(self.is_video_source, src=True)
 

	
 

	
 
class SoupModelMixin:
 
class SoupModelMixin(object):
 
    """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.
 
    """
 

	
 
    OG_PREVIEW_ATTR = 'data-ogpreview'
 
    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 _elem_key(self, attr_name=OG_PREVIEW_ATTR, getvalue=int, fallback=999999):
 
        def elem_sort_key(elem):
 
            try:
www/conservancy/middleware.py
Show inline comments
 
from builtins import object
 
from future.utils import raise_
 
from django import http
 
from django.conf import settings
 
from django.utils.cache import patch_response_headers
 

	
 
class ForceCanonicalHostnameMiddleware(object):
 

	
 
    def process_request(self, request):
 
        """Modified common middleware for Conservancy site
 

	
 
        * Performs redirects to strip trailing "index.html"
 
        * performs redirects based on APPEND_SLASH
 
        * performs redirects based on site-specific REDIRECT_TABLE
 
        * adds cache headers to provide hints to squid
 
        """
 

	
 
        # Never allow connection to the /admin part of the site without SSL
 
        if (not request.is_secure) and request.path.startswith('/admin'):
 
            url = 'https://sfconservancy.org%s' % request.path
 
            return http.HttpResponseRedirect(url)
 

	
 
        # Check for a redirect based on settings.APPEND_SLASH
 
        host = request.get_host()
 
        old_url = [host, request.path]
0 comments (0 inline, 0 general)