Changeset - b528902afb8f
[Not reviewed]
Merge
1 15 20
Christopher Neugebauer - 4 years ago 2017-10-04 23:03:47
chrisjrn@gmail.com
Merge branch 'refs/heads/master' into prod
35 files changed with 1705 insertions and 183 deletions:
0 comments (0 inline, 0 general)
fixtures/sitetree.json
Show inline comments
...
 
@@ -27,7 +27,7 @@
 
        "access_restricted": false,
 
        "access_perm_type": 1,
 
        "parent": null,
 
        "sort_order": 2,
 
        "sort_order": 7,
 
        "access_permissions": []
 
    }
 
},
...
 
@@ -51,7 +51,7 @@
 
        "access_restricted": false,
 
        "access_perm_type": 1,
 
        "parent": null,
 
        "sort_order": 8,
 
        "sort_order": 24,
 
        "access_permissions": []
 
    }
 
},
...
 
@@ -83,9 +83,9 @@
 
    "model": "sitetree.treeitem",
 
    "pk": 8,
 
    "fields": {
 
        "title": "Safety",
 
        "title": "Attend",
 
        "hint": "",
 
        "url": "/code-of-conduct",
 
        "url": "/attend",
 
        "urlaspattern": false,
 
        "tree": 1,
 
        "hidden": false,
...
 
@@ -99,7 +99,7 @@
 
        "access_restricted": false,
 
        "access_perm_type": 1,
 
        "parent": null,
 
        "sort_order": 9,
 
        "sort_order": 8,
 
        "access_permissions": []
 
    }
 
},
...
 
@@ -123,7 +123,7 @@
 
        "access_restricted": false,
 
        "access_perm_type": 1,
 
        "parent": null,
 
        "sort_order": 24,
 
        "sort_order": 25,
 
        "access_permissions": []
 
    }
 
},
...
 
@@ -171,7 +171,7 @@
 
        "access_restricted": false,
 
        "access_perm_type": 1,
 
        "parent": 1,
 
        "sort_order": 12,
 
        "sort_order": 13,
 
        "access_permissions": []
 
    }
 
},
...
 
@@ -195,55 +195,7 @@
 
        "access_restricted": false,
 
        "access_perm_type": 1,
 
        "parent": 1,
 
        "sort_order": 13,
 
        "access_permissions": []
 
    }
 
},
 
{
 
    "model": "sitetree.treeitem",
 
    "pk": 14,
 
    "fields": {
 
        "title": "Reporting an Incident",
 
        "hint": "",
 
        "url": "/code-of-conduct/harassment-incidents",
 
        "urlaspattern": false,
 
        "tree": 1,
 
        "hidden": false,
 
        "alias": null,
 
        "description": "",
 
        "inmenu": true,
 
        "inbreadcrumbs": true,
 
        "insitetree": true,
 
        "access_loggedin": false,
 
        "access_guest": false,
 
        "access_restricted": false,
 
        "access_perm_type": 1,
 
        "parent": 8,
 
        "sort_order": 15,
 
        "access_permissions": []
 
    }
 
},
 
{
 
    "model": "sitetree.treeitem",
 
    "pk": 15,
 
    "fields": {
 
        "title": "Staff Procedures",
 
        "hint": "",
 
        "url": "/code-of-conduct/harassment-staff-procedures",
 
        "urlaspattern": false,
 
        "tree": 1,
 
        "hidden": false,
 
        "alias": null,
 
        "description": "",
 
        "inmenu": true,
 
        "inbreadcrumbs": true,
 
        "insitetree": true,
 
        "access_loggedin": false,
 
        "access_guest": false,
 
        "access_restricted": false,
 
        "access_perm_type": 1,
 
        "parent": 8,
 
        "sort_order": 17,
 
        "sort_order": 33,
 
        "access_permissions": []
 
    }
 
},
...
 
@@ -267,7 +219,7 @@
 
        "access_restricted": false,
 
        "access_perm_type": 1,
 
        "parent": 8,
 
        "sort_order": 14,
 
        "sort_order": 37,
 
        "access_permissions": []
 
    }
 
},
...
 
@@ -328,7 +280,7 @@
 
        "url": "/program",
 
        "urlaspattern": false,
 
        "tree": 1,
 
        "hidden": true,
 
        "hidden": false,
 
        "alias": null,
 
        "description": "",
 
        "inmenu": true,
...
 
@@ -339,7 +291,7 @@
 
        "access_restricted": false,
 
        "access_perm_type": 1,
 
        "parent": null,
 
        "sort_order": 7,
 
        "sort_order": 9,
 
        "access_permissions": []
 
    }
 
},
...
 
@@ -349,8 +301,8 @@
 
    "fields": {
 
        "title": "Log In",
 
        "hint": "",
 
        "url": "nbpy_login",
 
        "urlaspattern": true,
 
        "url": "/account/login/",
 
        "urlaspattern": false,
 
        "tree": 1,
 
        "hidden": false,
 
        "alias": null,
...
 
@@ -363,7 +315,7 @@
 
        "access_restricted": false,
 
        "access_perm_type": 1,
 
        "parent": null,
 
        "sort_order": 26,
 
        "sort_order": 29,
 
        "access_permissions": []
 
    }
 
},
...
 
@@ -387,7 +339,7 @@
 
        "access_restricted": false,
 
        "access_perm_type": 1,
 
        "parent": null,
 
        "sort_order": 29,
 
        "sort_order": 30,
 
        "access_permissions": []
 
    }
 
},
...
 
@@ -459,7 +411,199 @@
 
        "access_restricted": false,
 
        "access_perm_type": 1,
 
        "parent": null,
 
        "sort_order": 25,
 
        "sort_order": 26,
 
        "access_permissions": []
 
    }
 
},
 
{
 
    "model": "sitetree.treeitem",
 
    "pk": 30,
 
    "fields": {
 
        "title": "North Bay Python",
 
        "hint": "",
 
        "url": "/",
 
        "urlaspattern": false,
 
        "tree": 1,
 
        "hidden": true,
 
        "alias": null,
 
        "description": "",
 
        "inmenu": true,
 
        "inbreadcrumbs": true,
 
        "insitetree": true,
 
        "access_loggedin": false,
 
        "access_guest": false,
 
        "access_restricted": false,
 
        "access_perm_type": 1,
 
        "parent": null,
 
        "sort_order": 2,
 
        "access_permissions": []
 
    }
 
},
 
{
 
    "model": "sitetree.treeitem",
 
    "pk": 31,
 
    "fields": {
 
        "title": "Make a Donation",
 
        "hint": "",
 
        "url": "/donate",
 
        "urlaspattern": false,
 
        "tree": 1,
 
        "hidden": false,
 
        "alias": null,
 
        "description": "",
 
        "inmenu": true,
 
        "inbreadcrumbs": true,
 
        "insitetree": true,
 
        "access_loggedin": false,
 
        "access_guest": false,
 
        "access_restricted": false,
 
        "access_perm_type": 1,
 
        "parent": 3,
 
        "sort_order": 31,
 
        "access_permissions": []
 
    }
 
},
 
{
 
    "model": "sitetree.treeitem",
 
    "pk": 32,
 
    "fields": {
 
        "title": "Events",
 
        "hint": "",
 
        "url": "/program/events",
 
        "urlaspattern": false,
 
        "tree": 1,
 
        "hidden": false,
 
        "alias": null,
 
        "description": "",
 
        "inmenu": true,
 
        "inbreadcrumbs": true,
 
        "insitetree": true,
 
        "access_loggedin": false,
 
        "access_guest": false,
 
        "access_restricted": false,
 
        "access_perm_type": 1,
 
        "parent": 24,
 
        "sort_order": 32,
 
        "access_permissions": []
 
    }
 
},
 
{
 
    "model": "sitetree.treeitem",
 
    "pk": 33,
 
    "fields": {
 
        "title": "Petaluma",
 
        "hint": "",
 
        "url": "/about/petaluma",
 
        "urlaspattern": false,
 
        "tree": 1,
 
        "hidden": false,
 
        "alias": null,
 
        "description": "",
 
        "inmenu": true,
 
        "inbreadcrumbs": true,
 
        "insitetree": true,
 
        "access_loggedin": false,
 
        "access_guest": false,
 
        "access_restricted": false,
 
        "access_perm_type": 1,
 
        "parent": 1,
 
        "sort_order": 12,
 
        "access_permissions": []
 
    }
 
},
 
{
 
    "model": "sitetree.treeitem",
 
    "pk": 34,
 
    "fields": {
 
        "title": "Buy a Ticket",
 
        "hint": "",
 
        "url": "/attend",
 
        "urlaspattern": false,
 
        "tree": 1,
 
        "hidden": false,
 
        "alias": null,
 
        "description": "",
 
        "inmenu": true,
 
        "inbreadcrumbs": true,
 
        "insitetree": true,
 
        "access_loggedin": false,
 
        "access_guest": false,
 
        "access_restricted": false,
 
        "access_perm_type": 1,
 
        "parent": 8,
 
        "sort_order": 14,
 
        "access_permissions": []
 
    }
 
},
 
{
 
    "model": "sitetree.treeitem",
 
    "pk": 35,
 
    "fields": {
 
        "title": "How to Pitch Your Manager",
 
        "hint": "",
 
        "url": "/attend/business-cases",
 
        "urlaspattern": false,
 
        "tree": 1,
 
        "hidden": false,
 
        "alias": null,
 
        "description": "",
 
        "inmenu": true,
 
        "inbreadcrumbs": true,
 
        "insitetree": true,
 
        "access_loggedin": false,
 
        "access_guest": false,
 
        "access_restricted": false,
 
        "access_perm_type": 1,
 
        "parent": 8,
 
        "sort_order": 15,
 
        "access_permissions": []
 
    }
 
},
 
{
 
    "model": "sitetree.treeitem",
 
    "pk": 36,
 
    "fields": {
 
        "title": "How to Get Here",
 
        "hint": "",
 
        "url": "/attend/travel",
 
        "urlaspattern": false,
 
        "tree": 1,
 
        "hidden": false,
 
        "alias": null,
 
        "description": "",
 
        "inmenu": true,
 
        "inbreadcrumbs": true,
 
        "insitetree": true,
 
        "access_loggedin": false,
 
        "access_guest": false,
 
        "access_restricted": false,
 
        "access_perm_type": 1,
 
        "parent": 8,
 
        "sort_order": 35,
 
        "access_permissions": []
 
    }
 
},
 
{
 
    "model": "sitetree.treeitem",
 
    "pk": 37,
 
    "fields": {
 
        "title": "Where to Stay",
 
        "hint": "",
 
        "url": "/attend/hotels",
 
        "urlaspattern": false,
 
        "tree": 1,
 
        "hidden": false,
 
        "alias": null,
 
        "description": "",
 
        "inmenu": true,
 
        "inbreadcrumbs": true,
 
        "insitetree": true,
 
        "access_loggedin": false,
 
        "access_guest": false,
 
        "access_restricted": false,
 
        "access_perm_type": 1,
 
        "parent": 8,
 
        "sort_order": 36,
 
        "access_permissions": []
 
    }
 
}
pinaxcon/registrasion/admin.py
Show inline comments
...
 
@@ -7,7 +7,3 @@ from django.utils.translation import ugettext_lazy as _
 
class UserProfileAdmin(admin.ModelAdmin):
 
    model = models.AttendeeProfile
 
    list_display = ("name", "company", "name_per_invoice")
 

	
 
@admin.register(models.DynamicValues)
 
class DynamicValuesAdmin(admin.ModelAdmin):
 
    pass
pinaxcon/registrasion/management/__init__.py
Show inline comments
 
new file 100644
pinaxcon/registrasion/management/commands/__init__.py
Show inline comments
 
new file 100644
pinaxcon/registrasion/management/commands/populate_inventory.py
Show inline comments
 
new file 100644
 
from collections import namedtuple
 
from datetime import datetime
 
from datetime import timedelta
 
from decimal import Decimal
 
from django.contrib.auth.models import Group
 
from django.core.exceptions import ObjectDoesNotExist
 
from django.core.management.base import BaseCommand, CommandError
 

	
 
from registrasion.models import inventory as inv
 
from registrasion.models import conditions as cond
 
from symposion import proposals
 

	
 
class Command(BaseCommand):
 
    help = 'Populates the inventory with the NBPy2017 inventory model'
 

	
 
    def add_arguments(self, parser):
 
        pass
 

	
 
    def handle(self, *args, **options):
 

	
 
        kinds = []
 
        for i in ("talk", ):
 
            kinds.append(proposals.models.ProposalKind.objects.get(name=i))
 
        self.main_conference_proposals = kinds
 

	
 
        self.populate_groups()
 
        self.populate_inventory()
 
        self.populate_restrictions()
 
        self.populate_discounts()
 

	
 
    def populate_groups(self):
 
        self.group_team = self.find_or_make(
 
            Group,
 
            ("name", ),
 
            name="Conference organisers",
 
        )
 
        self.group_volunteers = self.find_or_make(
 
            Group,
 
            ("name", ),
 
            name="Conference volunteers",
 
        )
 
        self.group_unpublish = self.find_or_make(
 
            Group,
 
            ("name", ),
 
            name="Can see unpublished products",
 
        )
 

	
 
    def populate_inventory(self):
 
        # Categories
 

	
 
        self.ticket = self.find_or_make(
 
            inv.Category,
 
            ("name",),
 
            name="Ticket",
 
            description="Each type of ticket has different included products. "
 
                        "For details of what products are included, see our "
 
                        "<a href='/attend'>ticket sales page</a>.",
 
            required = True,
 
            render_type=inv.Category.RENDER_TYPE_RADIO,
 
            limit_per_user=1,
 
            order=1,
 
        )
 
        self.t_shirt = self.find_or_make(
 
            inv.Category,
 
            ("name",),
 
            name="T-Shirt",
 
            description="Commemorative conference t-shirts, featuring secret "
 
                        "North Bay Python 2017 artwork. Details of sizing and "
 
                        "manufacturer are on our <a href='/attend/tshirt'>"
 
                        "t-shirts page</a>",
 
            required = False,
 
            render_type=inv.Category.RENDER_TYPE_ITEM_QUANTITY,
 
            order=40,
 
        )
 
        self.extras = self.find_or_make(
 
            inv.Category,
 
            ("name",),
 
            name="Extras",
 
            description="Other items that can improve your conference "
 
                        "experience.",
 
            required = False,
 
            render_type=inv.Category.RENDER_TYPE_QUANTITY,
 
            order=60,
 
        )
 

	
 
        # Tickets
 

	
 
        self.ticket_ind_sponsor = self.find_or_make(
 
            inv.Product,
 
            ("name", "category",),
 
            category=self.ticket,
 
            name="Individual Sponsor",
 
            price=Decimal("500.00"),
 
            reservation_duration=hours(24),
 
            order=1,
 
        )
 
        self.ticket_corporate = self.find_or_make(
 
            inv.Product,
 
            ("name", "category",),
 
            category=self.ticket,
 
            name="Corporate",
 
            price=Decimal("200.00"),
 
            reservation_duration=hours(24),
 
            order=10,
 
        )
 
        self.ticket_supporter = self.find_or_make(
 
            inv.Product,
 
            ("name", "category",),
 
            category=self.ticket,
 
            name="Individual Supporter",
 
            price=Decimal("100.00"),
 
            reservation_duration=hours(24),
 
            order=20,
 
        )
 
        self.ticket_unaffiliated = self.find_or_make(
 
            inv.Product,
 
            ("name", "category",),
 
            category=self.ticket,
 
            name="Unaffiliated Individual",
 
            price=Decimal("50.00"),
 
            reservation_duration=hours(24),
 
            order=30,
 
        )
 
        self.ticket_speaker = self.find_or_make(
 
            inv.Product,
 
            ("name", "category",),
 
            category=self.ticket,
 
            name="Speaker",
 
            price=Decimal("00.00"),
 
            reservation_duration=hours(24),
 
            order=50,
 
        )
 
        self.ticket_media = self.find_or_make(
 
            inv.Product,
 
            ("name", "category",),
 
            category=self.ticket,
 
            name="Media",
 
            price=Decimal("00.00"),
 
            reservation_duration=hours(24),
 
            order=60,
 
        )
 
        self.ticket_sponsor = self.find_or_make(
 
            inv.Product,
 
            ("name", "category",),
 
            category=self.ticket,
 
            name="Sponsor",
 
            price=Decimal("00.00"),
 
            reservation_duration=hours(24),
 
            order=70,
 
        )
 
        self.ticket_team = self.find_or_make(
 
            inv.Product,
 
            ("name", "category",),
 
            category=self.ticket,
 
            name="Conference Organiser",
 
            price=Decimal("00.00"),
 
            reservation_duration=hours(24),
 
            order=80,
 
        )
 
        self.ticket_volunteer = self.find_or_make(
 
            inv.Product,
 
            ("name", "category",),
 
            category=self.ticket,
 
            name="Conference Volunteer",
 
            price=Decimal("00.00"),
 
            reservation_duration=hours(24),
 
            order=90,
 
        )
 

	
 
        # Shirts
 
        ShirtGroup = namedtuple("ShirtGroup", ("prefix", "sizes"))
 
        shirt_names = {
 
            "mens": ShirtGroup(
 
                "Men's/Straight Cut Size",
 
                ("S", "M", "L", "XL", "2XL", "3XL", "5XL"),
 
            ),
 
            "womens_classic": ShirtGroup(
 
                "Women's Relaxed Fit",
 
                ("XS", "S", "M", "L", "XL", "2XL", "3XL"),
 
            ),
 
            "womens_semi": ShirtGroup(
 
                "Women's Semi-Fitted",
 
                ("S", "M", "L", "XL", "2XL", "3XL"),
 
            ),
 
        }
 

	
 
        self.shirts = {}
 
        order = 0
 
        for name, group in shirt_names.items():
 
            self.shirts[name] = {}
 
            prefix = group.prefix
 
            for size in group.sizes:
 
                product_name = "%s %s" % (prefix, size)
 
                order += 10
 
                self.shirts[name][size] = self.find_or_make(
 
                    inv.Product,
 
                    ("name", "category",),
 
                    name=product_name,
 
                    category=self.t_shirt,
 
                    price=Decimal("30.00"),
 
                    reservation_duration=hours(1),
 
                    order=order,
 
                )
 

	
 
    def populate_restrictions(self):
 

	
 
        # Hide the products that will eventually need a voucher
 
        hide_voucher_products = self.find_or_make(
 
            cond.GroupMemberFlag,
 
            ("description", ),
 
            description="Can see hidden products",
 
            condition=cond.FlagBase.ENABLE_IF_TRUE,
 
        )
 
        hide_voucher_products.group.set([self.group_unpublish])
 
        hide_voucher_products.products.set([
 
            self.ticket_media,
 
            self.ticket_sponsor,
 
        ])
 

	
 
        # Set limits.
 
        public_ticket_cap = self.find_or_make(
 
            cond.TimeOrStockLimitFlag,
 
            ("description", ),
 
            description="Public ticket cap",
 
            condition=cond.FlagBase.DISABLE_IF_FALSE,
 
            limit=350,
 
        )
 
        public_ticket_cap.products.set([
 
            self.ticket_ind_sponsor,
 
            self.ticket_corporate,
 
            self.ticket_supporter,
 
            self.ticket_unaffiliated,
 
        ])
 

	
 
        non_public_ticket_cap = self.find_or_make(
 
            cond.TimeOrStockLimitFlag,
 
            ("description", ),
 
            description="Non-public ticket cap",
 
            condition=cond.FlagBase.DISABLE_IF_FALSE,
 
            limit=200,
 
        )
 
        non_public_ticket_cap.products.set([
 
            self.ticket_speaker,
 
            self.ticket_sponsor,
 
            self.ticket_media,
 
            self.ticket_team,
 
            self.ticket_volunteer,
 
        ])
 

	
 
        # Volunteer tickets are for volunteers only
 
        volunteers = self.find_or_make(
 
            cond.GroupMemberFlag,
 
            ("description", ),
 
            description="Volunteer tickets",
 
            condition=cond.FlagBase.ENABLE_IF_TRUE,
 
        )
 
        volunteers.group.set([self.group_volunteers])
 
        volunteers.products.set([
 
            self.ticket_volunteer,
 
        ])
 

	
 
        # Team tickets are for team members only
 
        team = self.find_or_make(
 
            cond.GroupMemberFlag,
 
            ("description", ),
 
            description="Team tickets",
 
            condition=cond.FlagBase.ENABLE_IF_TRUE,
 
        )
 
        team.group.set([self.group_team])
 
        team.products.set([
 
            self.ticket_team,
 
        ])
 

	
 
        # Speaker tickets are for primary speakers only
 
        speaker_tickets = self.find_or_make(
 
            cond.SpeakerFlag,
 
            ("description", ),
 
            description="Speaker tickets",
 
            condition=cond.FlagBase.ENABLE_IF_TRUE,
 
            is_presenter=True,
 
            is_copresenter=False,
 
        )
 
        speaker_tickets.proposal_kind.set(self.main_conference_proposals)
 
        speaker_tickets.products.set([self.ticket_speaker, ])
 

	
 
    def populate_discounts(self):
 

	
 
        def add_early_birds(discount):
 
            self.find_or_make(
 
                cond.DiscountForProduct,
 
                ("discount", "product"),
 
                discount=discount,
 
                product=self.ticket_ind_sponsor,
 
                price=Decimal("50.00"),
 
                quantity=1,  # Per user
 
            )
 
            self.find_or_make(
 
                cond.DiscountForProduct,
 
                ("discount", "product"),
 
                discount=discount,
 
                product=self.ticket_corporate,
 
                price=Decimal("20.00"),
 
                quantity=1,  # Per user
 
            )
 
            self.find_or_make(
 
                cond.DiscountForProduct,
 
                ("discount", "product"),
 
                discount=discount,
 
                product=self.ticket_supporter,
 
                price=Decimal("20.00"),
 
                quantity=1,  # Per user
 
            )
 
            self.find_or_make(
 
                cond.DiscountForProduct,
 
                ("discount", "product"),
 
                discount=discount,
 
                product=self.ticket_unaffiliated,
 
                price=Decimal("25.00"),
 
                quantity=1,  # Per user
 
            )
 

	
 
        def free_category(parent_discount, category, quantity=1):
 
            self.find_or_make(
 
                cond.DiscountForCategory,
 
                ("discount", "category",),
 
                discount=parent_discount,
 
                category=category,
 
                percentage=Decimal("100.00"),
 
                quantity=quantity,
 
            )
 

	
 
        # Early Bird Discount (general public)
 
        early_bird = self.find_or_make(
 
            cond.TimeOrStockLimitDiscount,
 
            ("description", ),
 
            description="Early Bird",
 
            end_time=datetime(year=2017, month=10, day=20),
 
            limit=100,  # Across all users
 
        )
 
        add_early_birds(early_bird)
 

	
 
        # Early bird rates for speakers
 
        speaker_ticket_discounts = self.find_or_make(
 
            cond.SpeakerDiscount,
 
            ("description", ),
 
            description="Speaker Ticket Discount",
 
            is_presenter=True,
 
            is_copresenter=True,
 
        )
 
        speaker_ticket_discounts.proposal_kind.set(
 
            self.main_conference_proposals,
 
        )
 
        add_early_birds(speaker_ticket_discounts)
 

	
 
        # Professional-Like ticket inclusions
 
        ticket_prolike_inclusions = self.find_or_make(
 
            cond.IncludedProductDiscount,
 
            ("description", ),
 
            description="Complimentary for ticket holder (Supporter-level and above)",
 
        )
 
        ticket_prolike_inclusions.enabling_products.set([
 
            self.ticket_ind_sponsor,
 
            self.ticket_corporate,
 
            self.ticket_supporter,
 
            self.ticket_sponsor,
 
            self.ticket_speaker,
 
        ])
 
        free_category(ticket_prolike_inclusions, self.t_shirt)
 

	
 
        # Team & volunteer ticket inclusions
 
        ticket_staff_inclusions = self.find_or_make(
 
            cond.IncludedProductDiscount,
 
            ("description", ),
 
            description="Complimentary for ticket holder (staff/volunteer)",
 
        )
 
        ticket_staff_inclusions.enabling_products.set([
 
            self.ticket_team,
 
            self.ticket_volunteer,
 
        ])
 

	
 
        # Team & volunteer t-shirts, regardless of ticket type
 
        staff_t_shirts = self.find_or_make(
 
            cond.GroupMemberDiscount,
 
            ("description", ),
 
            description="T-shirts complimentary for staff and volunteers",
 
        )
 
        staff_t_shirts.group.set([
 
            self.group_team,
 
            self.group_volunteers,
 
        ])
 
        free_category(staff_t_shirts, self.t_shirt, quantity=2)
 

	
 
    def find_or_make(self, model, search_keys, **k):
 
        ''' Either makes or finds an object of type _model_, with the given
 
        kwargs.
 

	
 
        Arguments:
 
            search_keys ([str, ...]): A sequence of keys that are used to search
 
            for an existing version in the database. The remaining arguments are
 
            only used when creating a new object.
 
        '''
 

	
 
        try:
 
            keys = dict((key, k[key]) for key in search_keys)
 
            a = model.objects.get(**keys)
 
            self.stdout.write("FOUND  : " + str(keys))
 
            model.objects.filter(id=a.id).update(**k)
 
            a.refresh_from_db()
 
            return a
 
        except ObjectDoesNotExist:
 
            a = model.objects.create(**k)
 
            self.stdout.write("CREATED: " + str(k))
 
            return a
 

	
 

	
 
def hours(n):
 
    return timedelta(hours=n)
pinaxcon/registrasion/migrations/0003_auto_20171002_1719.py
Show inline comments
 
new file 100644
 
# -*- coding: utf-8 -*-
 
# Generated by Django 1.11.5 on 2017-10-03 00:19
 
from __future__ import unicode_literals
 

	
 
from django.db import migrations, models
 
import django_countries.fields
 

	
 

	
 
class Migration(migrations.Migration):
 

	
 
    dependencies = [
 
        ('pinaxcon_registrasion', '0002_auto_20161005_1823'),
 
    ]
 

	
 
    operations = [
 
        migrations.RemoveField(
 
            model_name='attendeeprofile',
 
            name='db_defined_values',
 
        ),
 
        migrations.RemoveField(
 
            model_name='attendeeprofile',
 
            name='dietary_requirements',
 
        ),
 
        migrations.RemoveField(
 
            model_name='attendeeprofile',
 
            name='free_text_1',
 
        ),
 
        migrations.RemoveField(
 
            model_name='attendeeprofile',
 
            name='free_text_2',
 
        ),
 
        migrations.RemoveField(
 
            model_name='attendeeprofile',
 
            name='of_legal_age',
 
        ),
 
        migrations.AddField(
 
            model_name='attendeeprofile',
 
            name='address_line_1',
 
            field=models.CharField(blank=True, help_text=b'This address, if provided, will appear on your receipt.', max_length=1024, verbose_name=b'Address line 1'),
 
        ),
 
        migrations.AddField(
 
            model_name='attendeeprofile',
 
            name='address_line_2',
 
            field=models.CharField(blank=True, max_length=1024, verbose_name=b'Address line 2'),
 
        ),
 
        migrations.AddField(
 
            model_name='attendeeprofile',
 
            name='address_postcode',
 
            field=models.CharField(blank=True, max_length=1024, verbose_name=b'Postal/Zip code'),
 
        ),
 
        migrations.AddField(
 
            model_name='attendeeprofile',
 
            name='address_suburb',
 
            field=models.CharField(blank=True, max_length=1024, verbose_name=b'City/Town/Suburb'),
 
        ),
 
        migrations.AddField(
 
            model_name='attendeeprofile',
 
            name='country',
 
            field=django_countries.fields.CountryField(default=b'US', max_length=2),
 
        ),
 
        migrations.AddField(
 
            model_name='attendeeprofile',
 
            name='dietary_restrictions',
 
            field=models.CharField(blank=True, max_length=256, verbose_name=b'Food allergies, intolerances, or dietary restrictions'),
 
        ),
 
        migrations.AddField(
 
            model_name='attendeeprofile',
 
            name='newsletter',
 
            field=models.BooleanField(default=False, help_text=b'Select to be subscribed to the low-volume North Bay Python announcements newsletter', verbose_name=b'Subscribe to North Bay Python newsletter'),
 
            preserve_default=False,
 
        ),
 
        migrations.AddField(
 
            model_name='attendeeprofile',
 
            name='state',
 
            field=models.CharField(blank=True, max_length=256, verbose_name=b'State/Territory/Province'),
 
        ),
 
        migrations.AlterField(
 
            model_name='attendeeprofile',
 
            name='accessibility_requirements',
 
            field=models.CharField(blank=True, max_length=256, verbose_name=b'Accessibility-related requirements'),
 
        ),
 
        migrations.AlterField(
 
            model_name='attendeeprofile',
 
            name='company',
 
            field=models.CharField(blank=True, help_text=b"The name of your company, as you'd like it on your badge and receipt", max_length=64),
 
        ),
 
        migrations.AlterField(
 
            model_name='attendeeprofile',
 
            name='gender',
 
            field=models.CharField(blank=True, help_text=b'Gender data will only be used for demographic purposes.', max_length=64),
 
        ),
 
        migrations.AlterField(
 
            model_name='attendeeprofile',
 
            name='name_per_invoice',
 
            field=models.CharField(blank=True, help_text=b"If your legal name is different to the name on your badge, fill this in, and we'll put it on your receipt. Otherwise, leave it blank.", max_length=256, verbose_name=b'Your legal name (for your receipt)'),
 
        ),
 
        migrations.DeleteModel(
 
            name='DemoPayment',
 
        ),
 
        migrations.DeleteModel(
 
            name='DynamicValues',
 
        ),
 
    ]
pinaxcon/registrasion/migrations/0004_attendeeprofile_agreement.py
Show inline comments
 
new file 100644
 
# -*- coding: utf-8 -*-
 
# Generated by Django 1.11.5 on 2017-10-04 13:15
 
from __future__ import unicode_literals
 

	
 
from django.db import migrations, models
 

	
 

	
 
class Migration(migrations.Migration):
 

	
 
    dependencies = [
 
        ('pinaxcon_registrasion', '0003_auto_20171002_1719'),
 
    ]
 

	
 
    operations = [
 
        migrations.AddField(
 
            model_name='attendeeprofile',
 
            name='agreement',
 
            field=models.BooleanField(default=False, help_text=b"I agree to act according to the conference <a href='/code-of-conduct'>Code of Conduct</a>. I also agree with the North Bay Python <a href='/terms'>Terms and Conditions</a>.", verbose_name=b'Agreement'),
 
        ),
 
    ]
pinaxcon/registrasion/models.py
Show inline comments
 
from django.core.exceptions import ValidationError
 
from django.db import models
 
from django.utils.encoding import python_2_unicode_compatible
 
from django_countries.fields import CountryField
 
from registrasion import models as rego
 

	
 

	
 
@python_2_unicode_compatible
 
class DynamicValues(models.Model):
 

	
 
    name = models.CharField(max_length=64)
 
    value = models.IntegerField()
 

	
 
    def __str__(self):
 
        return "%s - %d" % (self.name, self.value)
 

	
 

	
 
class AttendeeProfile(rego.AttendeeProfileBase):
 

	
 
    @classmethod
...
 
@@ -22,11 +14,55 @@ class AttendeeProfile(rego.AttendeeProfileBase):
 
        return "name"
 

	
 
    def invoice_recipient(self):
 

	
 
        lines = [
 
            self.name_per_invoice,
 
        ]
 

	
 
        if self.company:
 
            base = "\n%(company)s\nAttention: %(name_per_invoice)s"
 
        else:
 
            base = "%(name_per_invoice)s"
 
        return base % self.__dict__
 
            lines.append("C/- " + self.company)
 

	
 
        if self.address_line_1:
 
            lines.append(self.address_line_1)
 

	
 
        if self.address_line_2:
 
            lines.append(self.address_line_2)
 

	
 
        if self.address_suburb or self.address_postcode:
 
            lines.append("%s %s" % (
 
                self.address_suburb or "",
 
                self.address_postcode or "",
 
            ))
 

	
 
        if self.state:
 
            lines.append(self.state)
 

	
 
        if self.country:
 
            lines.append(self.country.name)
 

	
 
        return "\n".join(unicode(line) for line in lines)
 

	
 
    def clean(self):
 
        errors = []
 
        if self.country == "US" and not self.state:
 
            errors.append(
 
                ("state", "US-based attendees must list their state"),
 
            )
 

	
 
        if self.address_line_2 and not self.address_line_1:
 
            errors.append((
 
                "address_line_1",
 
                "Please fill in line 1 before filling line 2",
 
            ))
 

	
 
        if not self.agreement:
 
            errors.append((
 
                "agreement",
 
                "You must accept the agreement.",
 
            ))
 

	
 
        if errors:
 
            raise ValidationError(dict(errors))
 

	
 
    def save(self):
 
        if not self.name_per_invoice:
...
 
@@ -42,56 +78,77 @@ class AttendeeProfile(rego.AttendeeProfileBase):
 

	
 
    company = models.CharField(
 
        max_length=64,
 
        help_text="The name of your company, as you'd like it on your badge",
 
        blank=True,
 
    )
 
    free_text_1 = models.CharField(
 
        max_length=64,
 
        verbose_name="Free text line 1",
 
        help_text="A line of free text that will appear on your badge. Use "
 
                  "this for your Twitter handle, IRC nick, your preferred "
 
                  "pronouns or anything else you'd like people to see on "
 
                  "your badge.",
 
        blank=True,
 
    )
 
    free_text_2 = models.CharField(
 
        max_length=64,
 
        verbose_name="Free text line 2",
 
        help_text="The name of your company, as you'd like it on your badge and receipt",
 
        blank=True,
 
    )
 

	
 
    # Other important Information
 
    name_per_invoice = models.CharField(
 
        verbose_name="Your legal name (for invoicing purposes)",
 
        max_length=64,
 
        verbose_name="Your legal name (for your receipt)",
 
        max_length=256,
 
        help_text="If your legal name is different to the name on your badge, "
 
                  "fill this in, and we'll put it on your invoice. Otherwise, "
 
                  "fill this in, and we'll put it on your receipt. Otherwise, "
 
                  "leave it blank.",
 
        blank=True,
 
        )
 
    of_legal_age = models.BooleanField(
 
        default=False,
 
        verbose_name="18+?",
 

	
 
    address_line_1 = models.CharField(
 
        verbose_name="Address line 1",
 
        help_text="This address, if provided, will appear on your receipt.",
 
        max_length=1024,
 
        blank=True,
 
    )
 
    address_line_2 = models.CharField(
 
        verbose_name="Address line 2",
 
        max_length=1024,
 
        blank=True,
 
    )
 
    dietary_requirements = models.CharField(
 
    address_suburb = models.CharField(
 
        verbose_name="City/Town/Suburb",
 
        max_length=1024,
 
        blank=True,
 
    )
 
    address_postcode = models.CharField(
 
        verbose_name="Postal/Zip code",
 
        max_length=1024,
 
        blank=True,
 
    )
 
    country = CountryField(
 
        default="US",
 
    )
 
    state = models.CharField(
 
        max_length=256,
 
        verbose_name="State/Territory/Province",
 
        blank=True,
 
    )
 

	
 
    dietary_restrictions = models.CharField(
 
        verbose_name="Food allergies, intolerances, or dietary restrictions",
 
        max_length=256,
 
        blank=True,
 
    )
 
    accessibility_requirements = models.CharField(
 
        verbose_name="Accessibility-related requirements",
 
        max_length=256,
 
        blank=True,
 
    )
 
    gender = models.CharField(
 
        help_text="Gender data will only be used for demographic purposes.",
 
        max_length=64,
 
        blank=True,
 
    )
 
    db_defined_values = models.ManyToManyField(
 
        DynamicValues
 
    )
 

	
 
    newsletter = models.BooleanField(
 
        verbose_name="Subscribe to North Bay Python newsletter",
 
        help_text="Select to be subscribed to the low-volume North Bay Python "
 
                  "announcements newsletter",
 
        blank=True,
 
    )
 

	
 
class DemoPayment(rego.PaymentBase):
 
    ''' A subclass of PaymentBase for use in our demo payments function. '''
 

	
 
    pass  # No custom features here, but yours could be here.
 
    agreement = models.BooleanField(
 
        verbose_name="Agreement",
 
        help_text="I agree to act according to the <a href='/code-of-conduct'> "
 
                  "North Bay Python Code of Conduct</a>. I also agree with the "
 
                  "North Bay Python <a href='/terms'>Terms and Conditions</a>.",
 
        blank=False,
 
        default=False,
 
    )
pinaxcon/settings.py
Show inline comments
...
 
@@ -289,6 +289,7 @@ PINAX_BOXES_HOOKSET = "pinaxcon.hooks.PinaxBoxesHookSet"
 

	
 
PINAX_STRIPE_PUBLIC_KEY = os.environ.get("STRIPE_PUBLIC_KEY", "your test public key")
 
PINAX_STRIPE_SECRET_KEY = os.environ.get("STRIPE_SECRET_KEY", "your test secret key")
 
TUOKCEHC_BASE_URL = os.environ.get("TUOKCEHC_BASE_URL", None)
 
PINAX_STRIPE_SEND_EMAIL_RECEIPTS = False
 

	
 
SYMPOSION_SPEAKER_MODEL = "pinaxcon.proposals.models.ConferenceSpeaker"
...
 
@@ -305,7 +306,7 @@ ATTENDEE_PROFILE_MODEL = "pinaxcon.registrasion.models.AttendeeProfile"
 
TICKET_PRODUCT_CATEGORY = 1
 

	
 

	
 
INVOICE_CURRENCY = "AUD"
 
INVOICE_CURRENCY = "USD"
 

	
 
# Use nose to run all tests
 
TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
...
 
@@ -320,5 +321,8 @@ NOSE_ARGS = [
 
MARKDOWN_DEUX_STYLES = {
 
    "default": {
 
        "safe_mode": False,
 
        "extras": {
 
            "tables": 1,
 
        }
 
    },
 
}
pinaxcon/templates/_footer.html
Show inline comments
...
 
@@ -14,8 +14,9 @@
 
      <a href="https://facebook.com/northbaypython">Facebook</a>
 
      | <a href="https://twitter.com/northbaypython">Twitter</a>
 
      | <a href="/code-of-conduct">Code of Conduct</a>
 
      | <a href="/terms">Terms and Conditions</a>
 
      | <a href="/about/colophon">Colophon</a>
 
      | <a href="/about/donate">Donate</a>
 
      | <a href="/donate">Donate</a>
 
    </p>
 

	
 
    <p>This site is <a href="https://github.com/northbaypython/website">free and open source software</a>, powered by <a href="https://github.com/chrisjrn/symposion/">Symposion</a> and <a href="https://github.com/chrisjrn/registrasion/">Registrasion</a>.</p>
pinaxcon/templates/dashboard.html
Show inline comments
...
 
@@ -30,6 +30,8 @@
 
      </div>
 
    </div>
 

	
 
    {% include "registrasion/dashboard_widget.html" %}
 

	
 
    <div class="panel panel-default">
 
        <div class="panel-heading">
 
            <div class="pull-right">
pinaxcon/templates/registrasion/dashboard_widget.html
Show inline comments
 
new file 100644
 
{% extends "registrasion/dashboard_widget_.html" %}
 

	
 
{% comment %}
 
  Blocks that you can override:
 

	
 
  - heading_actions
 
  - heading
 
  - panel_content
 
  - available_credit
 
  - invoices_heading
 
  - invoice_item_prefix
 

	
 
{% endcomment %}
 

	
 
{% block heading %}
 
  Tickets
 
{% endblock %}
 

	
 
{% block invoices_heading %}
 
  Statements &amp; Receipts
 
{% endblock %}
 

	
 
{% block invoice_item_prefix %}
 
  {% if invoice.is_paid %}
 
    Receipt
 
  {% else %}
 
    Statement
 
  {% endif %}
 
{% endblock %}
pinaxcon/templates/registrasion/emails/invoice_created/subject.txt
Show inline comments
 
new file 100644
 
{% load i18n %}Pending Registration {{ invoice.id }}
pinaxcon/templates/registrasion/emails/invoice_updated/subject.txt
Show inline comments
 
new file 100644
 
{% load i18n %}{{ invoice.get_status_display }} -- Registration {{ invoice.id }}
pinaxcon/templates/registrasion/invoice.html
Show inline comments
 
{% extends "registrasion/invoice_.html" %}
 

	
 
{% block payment_actions %}
 
  <a class="btn btn-default" href="{% url "demopay" invoice.id invoice.user.attendee.access_code %}">Pay this invoice (dummy)</a>
 
  {{ block.super }}
 
{% endblock %}
pinaxcon/templates/registrasion/invoice/details.html
Show inline comments
 
new file 100644
 
{% extends "registrasion/invoice/details_.html" %}
 
{% comment %}
 
  Blocks that you can override:
 

	
 
  - heading
 
  - subheading
 
  - invoice_intro
 
  - extra_line_items
 
  - contact_info
 

	
 
{% endcomment %}
 

	
 
{% block heading %}
 
  {% if invoice.is_paid or invoice.is_refunded %}
 
    Registration Receipt
 
  {% else %}
 
    Pending Registration
 
  {% endif %}
 
{% endblock %}
 

	
 
{% block subheading %}
 
  North Bay Python. December 2 &amp; 3 2017. Petaluma, California.
 
{% endblock %}
 

	
 
{% block invoice_intro %}
 
  {% if invoice.is_unpaid %}
 
    This is a registration summary for North Bay Python 2017. It is not confirmed until paid in full.
 
  {% elif invoice.is_void %}
 
    This is a void registration summary for North Bay Python 2017. It is provided for informational purposes only.
 
  {% elif invoice.is_refunded %}
 
    This is a refunded registration summary for North Bay Python 2017. It is provided for informational purposes only.
 
  {% elif invoice.is_paid %}
 
    This is a confirmed registration summary for North Bay Python 2017.
 
  {% endif %}
 

	
 
{% endblock %}
 

	
 
{% block contact_info %}
 
  <p>Direct inquiries to <a href="mailto:spam@northbaypython.org">spam@northbaypython.org</a></p>
 
  <p>North Bay Python is run by North Bay and Bay Area locals, as a member project of <a href="https://sfconservancy.org">Software Freedom Conservancy</a>, a 501(c)(3) public charity registered in New York.</p>
 

	
 
  <strong>Mailing Address</strong>
 
  <address>
 
    Software Freedom Conservancy, Inc.<br>
 
    137 MONTAGUE ST STE 380<br>
 
    Brooklyn, NY 11201-3548<br>
 
  </address>
 
{% endblock %}
pinaxcon/templates/registrasion/invoice/unpaid_notice.html
Show inline comments
 
new file 100644
 
<p><strong>NOTICE:</strong> The below statement is automatically generated, and will be voided if you amend your registration before payment, or if discounts or products contained in the statement become unavailable. The items and discounts are only reserved until the due time.</p>
 

	
 
{% url "invoice_access" invoice.user.attendee.access_code as access_url %}
 
{% url "invoice" invoice.id invoice.user.attendee.access_code as invoice_url %}
 

	
 
<p>You can send the following links to your accounts department to pay for your registration:</p>
 

	
 
<ul>
 
  <li>{{ current_host|add:access_url|urlize }} &ndash; your most recent statement or receipt</li>
 
  <li>{{ current_host|add:invoice_url|urlize }} &ndash; this statement, even if it becomes void.</li>
 
</ul>
pinaxcon/templates/registrasion/review.html
Show inline comments
 
new file 100644
 
{% extends "registrasion/review_.html" %}
 
{% comment %}
 
  Blocks that you can override:
 
  - selected_items_intro
 
  - purchased_items_intro
 
  - add_to_selection_intro
 
  - missing_categories_intro
 
  - non_missing_categories_intro
 
  - what_next_intro
 
{% endcomment %}
 

	
 
{% block selected_items_intro %}
 
  You've selected the following items, which will be on your statement when you check out:
 
{% endblock %}
pinaxcon/templates/registrasion/stripe/tuokcehc.html
Show inline comments
 
new file 100644
 
{% extends "registrasion/stripe/tuokcehc_.html" %}
 

	
 
{% block lede %}
 
  North Bay Python transactions are performed by Stripe on behalf of Software
 
  Freedom Conservancy.
 
{% endblock %}
pinaxcon/templates/static_pages/about/colophon.html
Show inline comments
...
 
@@ -36,7 +36,7 @@
 
<h2>Terms and Conditions</h2>
 

	
 
<p>
 
  Our Photography and Audio Video Recording policy is adapted from the <a href="https://evergreen-ils.org/conference/photography-policy/">Evergreen policy</a>, itself adapted from the <a href="https://adacamp.org/adacamp-toolkit/policies/#photo">AdaCamp policy</a> under a <a href="http://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution Share Alike 4.0 International</a> license.</p>
 
  Our <a href="/terms-and-conditions">Terms and Conditions</a> were forked from the <a href="https://github.com/linuxaustralia/constitution_and_policies/blob/master/terms_and_conditions.md">Linux Australia Event Terms and Conditions</a> under the <a href="https://creativecommons.org/licenses/by-sa/3.0/au/">Creative Commons Attribution Share Alike 3.0 Australia</a> license. Our Photography and Audio Video Recording policy is adapted from the <a href="https://evergreen-ils.org/conference/photography-policy/">Evergreen policy</a>, itself adapted from the <a href="https://adacamp.org/adacamp-toolkit/policies/#photo">AdaCamp policy</a> under a <a href="http://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution Share Alike 4.0 International</a> license.</p>
 

	
 
<h2>Web Application</h2>
 

	
...
 
@@ -49,4 +49,4 @@
 
  <li><a href="https://inkscape.org/">Inkscape</a> is used to create most of our graphics.</li>
 
</ul>
 

	
 
{% endblock %}
 
{% endblock %}
...
 
\ No newline at end of file
pinaxcon/templates/static_pages/about/north_bay_python.html
Show inline comments
...
 
@@ -18,8 +18,7 @@
 

	
 
<p>We're a nonprofit conference for professionals, enthusiasts and students alike. We're focused on inclusion, accessibility, diversity, and affordability. Most importantly, we're planning a great lineup of talks from all over the Python ecosystem, with plenty of time to meet new people and develop new ideas.</p>
 

	
 
<p>Our venue, the Mystic Theatre in Downtown Petaluma, is a beautiful example of an early 1900s Vaudeville theatre. You can find over 50 different food and drink options a short walk away, and the nearest hotel is only a block away.</p>
 

	
 
<p>Our venue, the Mystic Theatre in Downtown Petaluma, is a beautiful example of an early 1900s Vaudeville theatre. You can find over 50 different food and drink options within a short walk, and the nearest hotel is only a block away.</p>
 

	
 
<h2>The Conference</h2>
 

	
...
 
@@ -29,33 +28,8 @@
 

	
 
<p>Our goal is to keep prices as low as possible. That means we won't be catering lunch. Instead, you can look forward to extra-long lunch breaks you can use to explore all of the great food options around the venue.</p>
 

	
 
<h2>The Town</h2>
 

	
 
<h2>Petaluma, California</h2>
 

	
 
<p>North Bay Python's home is Petaluma, a delightfully quaint dairy town, nestled on a river at the southern edge of California's Wine Country. We've got beautiful scenery right on our doorstep, and we're less than an hour's drive from San Francisco over the Golden Gate Bridge.</p>
 

	
 
<p>The Mystic is not the only local example of early 1900s architecture, either: Downtown is full of great examples of Victorian-era buildings that survived the 1906 earthquake. Just down the road, you'll find the center of the maker movement and a thriving craft brewery scene.</p>
 

	
 

	
 
<h3>Getting Here</h3>
 

	
 
<h4>By Car</h4>
 

	
 
<p>If you're driving up, Downtown Petaluma is at exit 472 on Highway 101, 35 miles north of the Golden Gate Bridge. All parking is free in Petaluma, including in the undercover garages at Keller St and Theatre Square. Both garages are in short walking distance of the Mystic.</p>
 

	
 
<h4>By Bus</h4>
 

	
 
<p>Public transit to Petaluma is not great. You can take the 101 bus operated by Golden Gate Transit from downtown San Francisco, or south from Santa Rosa. Depending on sponsorship, we hope to run a free shuttle with BART and Caltrain connections for people from further out of town.</p>
 

	
 
<h4>By Plane</h4>
 

	
 
<p>If you're coming from out of the area, you may want to consider Sonoma County Airport (STS). STS is 30 minutes out of Petaluma, and has nonstop flights to most major west coast cities. If you can't make it to STS, you can also try San Francisco (SFO) or Oakland (OAK) international airports.</p>
 

	
 
<p>If you happen to have an aircraft of your own, Petaluma Municipal Airport is 3 miles down the road.</p>
 

	
 

	
 
<h3>Staying Here</h3>
 

	
 
<p>Petaluma also has hotels! We're arranging deals with some of the best local hotels in the area &ndash; the closest is just one block away. We'll share details with you when conference tickets go on sale.</p>
 
<p>North Bay Python's home is <a href="/about/petaluma">Petaluma</a>, a delightfully quaint dairy town, nestled on a river at the southern edge of California's Wine Country.</p>
 

	
 
{% endblock %}
pinaxcon/templates/static_pages/about/petaluma.html
Show inline comments
 
new file 100644
 
{% extends "page_with_title_and_lede.html" %}
 

	
 
{% load i18n %}
 

	
 
{% block head_title %}Petaluma{% endblock %}
 

	
 
{% block heading %}Petaluma{% endblock %}
 

	
 
{% block body_class %}about{% endblock %}
 

	
 
{% block lede %}
 
  The best town you probably haven't bothered visiting yet. 
 
{% endblock %}
 

	
 

	
 
{% block content %}
 

	
 
<p>North Bay Python's home is <a href="/about/petaluma">Petaluma</a>, a delightfully quaint dairy town, nestled on a river at the southern edge of California's Wine Country. We've got beautiful scenery right on our doorstep, and we're less than an hour's drive from San Francisco over the Golden Gate Bridge. We've got a whole page dedicated to <a href="/about/petaluma">Petaluma</a> if you want to learn more about it.</p>
 

	
 
<p>Our venue, The Mystic Theatre, is not the only local example of early 1900s architecture, either: Downtown is full of great examples of Victorian-era buildings that survived the 1906 earthquake. Just down the road, you'll find the center of the maker movement and a thriving craft brewery scene.</p>
 

	
 

	
 
<h2>Travel and Accommodation</h2>
 

	
 
<p>The Golden Gate Bridge is well-known to San Franciscans as being approximately 8,000 miles long and shrouded in fog, so few ever cross up into the North Bay. Happily, the drive north is easy and it can be swift. There are many ways to get to Petaluma, we've covered driving, public transit, and flights on the <a href="/attend/travel">How to Get Here</a> page.</p>
 

	
 
<p>When you get here, you're sure to find a nice place to stay that fits your budget. You can find a range of options, and some special discounts, available on the <a href="/attend/hotels">Where to Stay</a> page.</p>
 

	
 
{% endblock %}
pinaxcon/templates/static_pages/attend/attend.html
Show inline comments
 
new file 100644
 
{% extends "page_with_title_and_lede.html" %}
 

	
 
{% load i18n %}
 
{% load markdown_deux_tags %}
 

	
 
{% block head_title %}Attend{% endblock %}
 

	
 
{% block heading %}Come to North Bay Python!{% endblock %}
 

	
 
{% block body_class %}attend{% endblock %}
 

	
 
{% block lede %}
 
  P-Town. Rivertown. That place where the cows are. No matter what you call Petaluma, we want you to join us here for a great weekend of Python talks and networking. North Bay Python tickets start at $25 for unaffiliated individuals, and $180 for corporate attendees.
 
{% endblock %}
 

	
 

	
 
{% block content %}
 

	
 
<p>To buy a ticket, <a href="/dashboard">create an account, and go to the dashboard</a>. If you've already bought a ticket, you can check out our information on <a href="/attend/hotels">where to stay</a> if you want to come up for the weekend, and <a href="/attend/travel">how to get here</a>.</p>
 

	
 
<br />
 

	
 
<div class="pull-right"><a class="btn btn-lg btn-primary" href="/tickets/buy">Buy a Ticket</a></div>
 
<h2>Which Ticket?</h2>
 

	
 
<p><em>Early Bird discounts are available for the first 100 tickets sold, or until October 20, whichever comes first. T-shirts are only available for tickets bought before November 7.</em></p>
 

	
 
<h3>Corporate <small>$200 ($180 Early Bird)</small></h3>
 

	
 
<p><strong>For company employees, and individuals who can claim the cost of attending the conference as a business expense or other tax deduction</strong>.</p>
 

	
 
<p>Includes a free t-shirt, and recognition of your affiliation on your conference badge and on the conference supporters list. Group discounts are available for organizations that buy 5 or more tickets.</p>
 

	
 
<h3>Individual Supporter <small>$100 ($80 Early Bird)</small></h3>
 

	
 
<p><strong>For individuals who want to financially contribute to the success of the conference.</strong></p>
 

	
 
<p>This ticket includes a free t-shirt, and recognition of your Free and Open Source Software, hobby, or nonprofit project on your conference badge.</p>
 

	
 
<h3>Unaffiliated Individual <small>$50 ($25 Early Bird)</small></h3>
 

	
 
<p><strong>For students, hobbyists, and unemployed/underemployed people who are coming to North Bay Python at their own expense.</strong></p>
 

	
 
<p>The cheapest ticket we can offer. You can add a t-shirt for $30.</p>
 

	
 

	
 
<h3>Special Tickets</h3>
 

	
 
<h4>Individual Sponsor <small>$500 ($450 Early Bird)</small></h4>
 

	
 
<p>This ticket includes all of the benefits of a Corporate ticket, but we’ll also give the ticket holder special thanks during our conference plenary sessions. You can also provide us with a promotional item to put in each attendee’s swag bag.</p>
 

	
 
<p>This ticket is for individuals who want to sponsor the conference. For company-level sponsorships, please see our <a href="/sponsors/become-a-sponsor">sponsorships page</a>.</p>
 

	
 

	
 
<h4>Group Discount Corporate <small>$180 for 5+ tickets</small></h4>
 

	
 
<p>For companies sending multiple attendees, you can get a 10% discount off the regular price on purchases of 5 tickets or more.</p>
 

	
 
<p>To claim, buy your first four tickets, and send us an email with the names and receipt numbers for those attendees. We’ll send you vouchers for a discount on further tickets.</p>
 

	
 

	
 
<h2>Ticket Types and Inclusions</h2>
 

	
 
<table class="table table-striped">
 
<tr>
 
  <th></th>
 
  <th>Unaffiliated Individual</th><th>Individual Supporter</th><th>  Corporate  </th><th> Individual Sponsor </th></tr>
 
<tr>
 
  <th>Regular Price</th>
 
  <td> $50 </td><td>$100</td><td> $200</td><td> $500
 
<tr>
 
  <th>Early Bird</th>
 
  <td> $25</td><td> $80 </td><td>$180</td><td> $450</td></tr>
 
<tr>
 
  <th>Group Discount</th>
 
  <td> - </td><td>- </td><td>$180/ticket for 5+ tickets</td><td> -</td></tr>
 
<tr>
 
  <th>Conference access</th>
 
  <td>  Yes </td><td>  Yes </td><td>  Yes </td><td>  Yes </td></tr>
 
<tr>
 
  <th>Morning refreshments</th>
 
  <td> TBA </td><td> TBA </td><td> TBA </td><td> TBA </td></tr>
 
<tr>
 
  <th>Free Lunch</th>
 
  <td> No </td><td> No </td><td> No </td><td> No </td></tr>
 
<tr>
 
  <th>T-Shirt</th>
 
  <td>$30 each</td><td>1 free</br>Extras $30 each</td><td>1 free</br>Extras $30 each</td><td>1 free</br>Extras $30 each</td></tr>
 
<tr>
 
  <th>Affiliation on your badge</th>
 
  <td> No </td><td>Personal projects only</td><td> Yes </td><td>Yes</td></tr>
 
<tr>
 
  <th>Supporter recognition</th>
 
  <td> None </td><td>For you </td><td>For you and your company </td><td>Top billing for you and your company or project</td></tr>
 
<tr>
 
  <th>Sponsor benefits</th>
 
  <td> No </td><td>No</td><td> No </td><td>Yes</td></tr>
 
</table>
 

	
 
<p>If you can’t afford to attend on these prices, please email <a href="mailto:spam@northbaypthon.org">spam@northbaypython.org</a> – we’ll enthusiastically waive ticket fees for people who need it.</em></p>
 

	
 
<div class="btn-group">
 
  <a class="btn btn-lg btn-primary" href="/tickets/buy">Buy a Ticket</a>
 
</div>
 

	
 

	
 
<h2>Benefits</h2>
 

	
 
<h3>Conference access</h3>
 
<p>Two days of high-caliber talks about Python, and meeting new Pythonistas at North Bay Python.</p>
 

	
 
<h3>Lunch</h3>
 
<p>In order to keep ticket costs as low as possible, we won’t be catering lunch this year.</p>
 

	
 
<p>To make up for it, we’ve located our conference right in the middle of Historic Downtown Petaluma’s restaurant district. You can find everything from market delis and barbecue, through to Michelin-rated restaurants, all within 5 minutes walk. You’ll get a better lunch than we’d ever be able to cater, for much less. We'll have a locals' guide to Petaluma to help you find places to eat.</p>
 

	
 
<h3>Morning Refreshments (TBA)</h3>
 
<p>If budget permits, or if we find a sponsor, we’ll provide coffee, tea, hot chocolate, and some light snacks in the morning before proceedings kick off on both days.</p>
 

	
 
<h3>T-Shirt</h3>
 
<p>We’ll be designing a collectible North Bay Python t-shirt for you to pick up at the conference, and they’ll be <a href="/attend/tshirt">available in a variety of sizes, cuts and colors</a>. Each t-shirt costs $30, and for supporter, corporate, and sponsor ticket holders, you’ll get your first t-shirt free!</p>
 

	
 
<p>T-shirts are available only for tickets purchased by Tuesday 7 November.</p>
 

	
 

	
 
<h3>Affiliation</h3>
 
<p>Every attendee gets their very own lanyard and a badge with their name on it. For higher-paying ticket holders, you’ll get your project’s name (supporter and above) or company name (corporate or sponsor levels only) on your badge, just below your name.</p>
 

	
 
<h3>Supporter Recognition</h3>
 
<p>On our website, we’ll have a list of our conference supporters. You can choose to have your name on that list.</p>
 

	
 
<p>For our corporate and sponsor ticket holders, we’ll also include your company name as part of those thanks.</p>
 

	
 
<h3>Sponsor Benefits</h3>
 
<p>Sponsor tickets come with sponsor benefits. To find out more, see our <a href="/sponsors/become-a-sponsor">Sponsors page</a>.</p>
 

	
 
{% endblock %}
pinaxcon/templates/static_pages/attend/business-case.html
Show inline comments
 
new file 100644
 
{% extends "page_with_title_and_lede.html" %}
 

	
 
{% load i18n %}
 

	
 
{% block head_title %}How to Pitch Your Manager{% endblock %}
 

	
 
{% block heading %}How to Pitch Your Manager{% endblock %}
 

	
 
{% block body_class %}attend{% endblock %}
 

	
 
{% block lede %}
 
So you want to attend North Bay Python, but you're not quite sure your manager will sign off on the expenses? Read below for some suggestions on how to make your case!
 
{% endblock %}
 

	
 

	
 
{% block content %}
 

	
 
<h3>Key Information</h3>
 
<p>
 
<ul>
 
    <li>Dates: Saturday, December 2nd and Sunday, December 3rd, 2017</li>
 
    <li>Venue: Mystic Theatre, Petaluma, California, USA</li>
 
    <li>Tickets: $200</li>
 
</ul>
 
</p>
 

	
 
<h3>How to Convince Your Boss</h3>
 

	
 
<p>
 
This comes down to building a <em>business case</em> for your attendance. Start by explaining what the conference is, why you want to go, and why your employer will benefit (we've helpfully included some of the great reasons you might use and some sample prose you're welcome to copy into your email, below).</p>
 

	
 
<p>Explain to your boss what you'll bring back for the rest of the team (ideas, not imbibables): offer to give a summary presentation at lunch, or post a write-up to the company wiki, upon your return. We have some fantastic content in store, and you'll have no trouble finding things to teach your teammates when you get back. Sessions will be recorded and posted to YouTube, so you'll have ready-to-share links for those who want additional detail. You could also share the names, Twitter handles, or business cards from the people you'll meet — some of them might even be interested in working with you!</p>
 

	
 
<h3>Sample Language</h3>
 
<p>
 
North Bay Python is a new, nonprofit conference by and for the Python community.
 
</p>
 

	
 
<p>
 
The conference features over 20 sessions from experienced presenters hailing from across the US and internationally, speaking on a wide mix of topics. Sessions will include updates from leading Python community members on the state of major projects, technical explorations of how Python and Python-based systems work in practice, and thought-provoking explorations and lessons on how best to communicate as a team, foster diversity and inclusivity, and effectively engage within and beyond our teams and communities as developers.
 
</p>
 

	
 
<p>Full details on the program will be released soon.</p>
 

	
 
<p>
 
Approximately 400 attendees from a diverse mix of backgrounds will be in Petaluma for the weekend, providing a rich opportunity for networking. Expect to meet key members of your favorite open source Python projects, fellow developers with novel perspectives on common problems, and maybe even some job-seekers to help bolster your organization's ranks.
 
</p>
 

	
 
<p>
 
Organizations funding attendees of North Bay Python can acquire competitive advantage by:
 
<ul>
 
    <li>Staying abreast of the latest libraries, services, and best practices in the Python ecosystem</li>
 
    <li>Learning techniques for architecting, authoring, deploying, and maintaining software</li>
 
    <li>Improving technical and organizational communication skills</li>
 
    <li>Networking with fellow Python users to establish potential future working relationships</li>
 
    <li>Returning to work refreshed and excited by all of the novel ways Python is being used across industries</li>
 
</ul>
 
</p>
 
{% endblock %}
pinaxcon/templates/static_pages/attend/hotels.html
Show inline comments
 
new file 100644
 
{% extends "page_with_title_and_lede.html" %}
 

	
 
{% load i18n %}
 

	
 
{% block head_title %}Where to Stay{% endblock %}
 

	
 
{% block heading %}Where to Stay{% endblock %}
 

	
 
{% block body_class %}attend{% endblock %}
 

	
 
{% block lede %}
 
  If you're coming from out of town, we'd love you to stay the night! We've made arrangements with the best hotels in Petaluma, with exclusive rates for North Bay Python attendees.
 
{% endblock %}
 

	
 

	
 
{% block content %}
 

	
 
<h2>Official Hotels</h2>
 

	
 
<p>We've made arrangements with three local accommodation providers to suit different budget options.</p>
 

	
 
<h3>Hotel Petaluma</h3>
 

	
 
<div class="row">
 
  <div class="col-md-7">
 
    <dl class="dl-horizontal">
 
      <dt>Where</dt><dd><a href="https://www.google.com/maps/dir/Mystic+Theatre,+Petaluma+Boulevard+North,+Petaluma,+CA/Hotel+Petaluma,+205+Kentucky+St,+Petaluma,+CA+94952">205 Kentucky St (0.2mi from venue)</a></dd>
 
      <dt>Price</dt><dd>$117-$153/night + tax</dd>
 
      <dt>Style</dt><dd>Limited-Service Hotel</dd>
 
      <dt>Book by</dt><dd>November 1st</dd>
 
    </dl>
 
  </div>
 
  <div class="col-md-2">
 
    <a class="btn btn-lg btn-primary" href="https://www.choicehotels.com/reservations/groups/GH6NY6">Book Hotel Petaluma</a>
 
  </div>
 
</div>
 

	
 
<p>The only hotel in Downtown Petaluma is a recently renovated boutique hotel in a 1920s-era building. It's a short walk from North Bay Python's venue, and is close to Petaluma's best places to eat and drink.</p>
 

	
 
<p>Hotel Petaluma has offered all of their available rooms to North Bay Python attendees, so if you want to stay as close as possible to the venue, book through our exclusive link by November 1st.</p>
 

	
 
<h3>Sheraton Petaluma</h3>
 

	
 
<div class="row">
 
  <div class="col-md-7">
 
    <dl class="dl-horizontal">
 
      <dt>Where</dt><dd>Petaluma Marina, <a href="https://www.google.com/maps/dir/Mystic+Theatre,+23+Petaluma+Blvd+N,+Petaluma,+CA+94952/Sheraton+Sonoma+County+-+Petaluma,+Baywood+Drive,+Petaluma,+CA">745 Baywood Dr (1.7mi from venue)</a></dd>
 
      <dt>Price</dt><dd>$129/night + tax</dd>
 
      <dt>Style</dt><dd>Full-Service Hotel</dd>
 
      <dt>Book by</dt><dd>November 17th</dd>
 
    </dl>
 
  </div>
 
  <div class="col-md-2">
 
    <a class="btn btn-lg btn-primary" href="https://www.starwoodmeeting.com/Book/NorthBayPython">Book Sheraton Petaluma</a>
 
  </div>
 
</div>
 

	
 
<p>The only full-service hotel in Petaluma operated by a major chain. The Sheraton sits on the riverfront at the Petaluma Marina, and is a short drive from the venue. Our exclusive rate of $129/night is available until November 17th.</p>
 

	
 

	
 

	
 
<h3>Quality Inn Petaluma</h3>
 

	
 
<div class="row">
 
  <div class="col-md-7">
 
    <dl class="dl-horizontal">
 
      <dt>Where</dt><dd><a href="https://www.google.com/maps/dir/Mystic+Theatre,+23+Petaluma+Blvd+N,+Petaluma,+CA+94952/Quality+Inn+Petaluma+-+Sonoma,+Montero+Way,+Petaluma,+CA">5100 Montero Way (3.7mi from venue)</a></dd>
 
      <dt>Price</dt><dd>from $81/night + tax</dd>
 
      <dt>Style</dt><dd>Motor Inn</dd>
 
      <dt>Book</dt><dd>while rooms last</dd>
 
    </dl>
 
  </div>
 
  <div class="col-md-2">
 
    <a class="btn btn-lg btn-primary" href="https://www.choicehotels.com/california/petaluma/quality-inn-hotels/ca056/rates?adults=2&checkInDate=2017-12-01&checkOutDate=2017-12-04&ratePlanCode=LEVNT">Book Quality Inn Petaluma</a>
 
  </div>
 
</div>
 

	
 
<p>A modern, comfortable motel at the northern end of the city is a great option for attendees looking to save money. North Bay Python attendees get 15% off the best published rate at the time of booking by using our exclusive booking link.</p>
 

	
 

	
 
<h2>Other options</h2>
 

	
 
<h3>In Petaluma</h3>
 

	
 
<p>There are other options for staying in Petaluma, that cater to a variety of budgets. We don't have an official relationship with these vendors, and provide these links for informational purposes only.</p>
 

	
 
<ul>
 
  <li>
 
    <strong><a href="http://www.metrolodging.com/">Metro Hotel</a></strong>. Boutique Hotel,
 
    <a href="https://www.google.com/maps/dir/Mystic+Theatre,+Petaluma+Boulevard+North,+Petaluma,+CA/Metro+Hotel+%26+Cafe,+508+Petaluma+Blvd+S,+Petaluma,+CA+94952">508 Petaluma Blvd S (0.4mi from venue)</a>
 
  </li>
 
  <li>
 
    <strong><a href="http://bestwesterncalifornia.com/hotels/best-western-petaluma-inn">Best Western Petaluma Inn</a></strong>. Motor Inn,
 
    <a href="https://www.google.com/maps/dir/Mystic+Theatre,+23+Petaluma+Blvd+N,+Petaluma,+CA+94952/Best+Western+Petaluma+Inn,+South+McDowell+Boulevard,+Petaluma,+CA">200 S McDowell Blvd (1.5mi from venue)</a>
 
  </li>
 
  <li>
 
    <strong><a href="http://www.petalumavalleyinn.com/">America's Best Value Inn &amp; Suites</a></strong>. Motor Inn,
 
    <a href="https://www.google.com/maps/dir/Americas+Best+Value+Inn+%26+Suites+Petaluma,+Montero+Way,+Petaluma,+CA/Mystic+Theatre,+23+Petaluma+Blvd+N,+Petaluma,+CA+94952">5135 Montero Way (3.7mi from venue)</a>
 
  </li>
 
  <li>
 
    <strong><a href="https://www.motel6.com/en/motels.ca.petaluma.1369.html">Motel 6</a></strong>. Motel,
 
    <a href="https://www.google.com/maps/dir/Motel+6+Petaluma,+North+McDowell+Boulevard,+Petaluma,+CA/Mystic+Theatre,+23+Petaluma+Blvd+N,+Petaluma,+CA+94952">1368 N McDowell Blvd (3.8mi from venue)</a>
 
  </li>
 
  <li>
 
    <strong><a href="https://koa.com/campgrounds/san-francisco/">KOA San Francisco North/Petaluma</a></strong>. Campground with self-contained cabins,
 
    <a href="https://www.google.com/maps/dir/San+Francisco+North+%2F+Petaluma+KOA,+Rainsville+Road,+Petaluma,+CA/Mystic+Theatre,+23+Petaluma+Blvd+N,+Petaluma,+CA+94952">20 Rainsville Rd (3.8mi from venue)</a>
 
  </li>
 
</ul>
 

	
 

	
 
<h3>Further Afield</h3>
 

	
 
<p>If you can't find something you're looking for in Petaluma, the nearby freeway town of Rohnert Park is 15 minutes drive away and has plenty of accommodation next to the freeway. People looking to spend obscene amounts of money may also be interested in the resort town of Sonoma, which is 20 minutes drive away.</p>
 

	
 
<p>Reasonable chain hotel and motel options also exist in Novato, however, we don't recommend staying there as traffic between there and Petaluma can be unpredictable.</p>
 

	
 

	
 
{% endblock %}
pinaxcon/templates/static_pages/attend/travel.html
Show inline comments
 
new file 100644
 
{% extends "page_with_title_and_lede.html" %}
 

	
 
{% load i18n %}
 

	
 
{% block head_title %}How to Get Here{% endblock %}
 

	
 
{% block heading %}How to Get Here{% endblock %}
 

	
 
{% block body_class %}attend{% endblock %}
 

	
 
{% block lede %}
 
  Chances are you're probably not in Petaluma, so if you want to come to North Bay Python, then you'll need to get here somehow. The good news is that it's reasonably easy to get here, whether you're coming from Sonoma County, elsewhere in the Bay Area, or from further out of town.
 
{% endblock %}
 

	
 

	
 
{% block content %}
 

	
 
<h2>By Car</h2>
 

	
 
<p>If you're driving up, Downtown Petaluma is at exit 472A on Highway 101, 35 miles north of the Golden Gate Bridge.</p>
 

	
 
<p>All parking is free in Petaluma, however near the Mystic, street-level parking is time-limited. All-day parking is available at street level west of 5th St (towards 6th St), and at the the undercover garages at <a href="https://www.google.com/maps/place/Keller+Street+Parking+Garage">Keller St</a> and at Theatre Square. Both garages are in short walking distance of the Mystic.</p>
 

	
 

	
 
<h2>By Public Transit</h2>
 

	
 
<p>Public transit to Petaluma is currently not great.</p>
 

	
 
<p>You can take the <a href="http://goldengatetransit.org/schedules/current/route_101.php">101 bus operated by Golden Gate Transit</a> from downtown San Francisco, or south from Santa Rosa. Depending on sponsorship, we hope to run a free shuttle with BART and Caltrain connections for people from further out of town.</p>
 

	
 
<p><a href="https://sonomamarintrain.org">SMART</a>, the new train service that runs along the 101 corridor, recently started operations. SMART is not suitable for getting to North Bay Python if you travel on weekends, as the first train leaves after proceedings start. SMART may be a better option than taking the bus between San Rafael and Petaluma if you travel up on weekdays.</p>
 

	
 

	
 
<h2>By Plane</h2>
 

	
 
<p>Petaluma is within driving distance of all Bay Area Airports, and each airport has varying levels of public transit links to Petaluma.</p>
 

	
 
<h4>Sonoma County Airport (STS) <small>25mi from venue</small></h4>
 

	
 
<p>STS is 30 minutes out of Petaluma, and has nonstop flights to most major west coast cities on Alaska, United, and American.</p>
 

	
 
<p>On weekdays and weekend afternoons, <a href="https://sonomamarintrain.org">SMART train</a> runs from STS to Downtown Petaluma Station, 1/4mi away from the North Bay Python venue. STS is also serviced by the <a href="http://airportexpressinc.com/schedule.php">Sonoma County Airport Express</a> bus.</p>
 

	
 
<h4>San Francisco International (SFO)/Oakland International (OAK) <small>50mi from venue</small></h4>
 

	
 
<p>If you can't make it to STS, you can also try San Francisco (SFO) or Oakland (OAK) international airports. These have many more flights than STS, but are twice the distance away, and are subject to more highway traffic between the airport and Petaluma.</p>
 

	
 
<p>Transfers to Petaluma are available through the <a href="http://airportexpressinc.com/schedule.php">Sonoma County Airport Express</a>.</p>
 

	
 
<h4>San Jose International (SJC)/Sacramento (SMF) <small>85mi from venue</small></h4>
 

	
 
<p>If you're planning on renting a car, San Jose (SJC) or Sacramento (SMF) are both two hours drive away.</p>
 

	
 
<h4>Petaluma Municipal <small>3mi from venue</small></h4>
 

	
 
<p>If you happen to have an aircraft of your own, Petaluma Municipal Airport is 3 miles down the road.</p>
 

	
 
{% endblock %}
pinaxcon/templates/static_pages/attend/tshirt.html
Show inline comments
 
new file 100644
 
{% extends "page_with_title_and_lede.html" %}
 

	
 
{% load i18n %}
 

	
 
{% block head_title %}T-Shirts{% endblock %}
 

	
 
{% block heading %}T-Shirt sizes and cuts{% endblock %}
 

	
 
{% block body_class %}attend{% endblock %}
 

	
 
{% block lede %}
 

	
 
{% endblock %}
 

	
 
{% block content %}
 

	
 
<p>North Bay Python uses Gildan t-shirts, and this year's design will be available in a variety of colours that you can choose from when you collect your shirt. There are three varieties available:</p>
 

	
 
<ul>
 
  <li>The Men's/Straight-Cut option is the <a href="http://www.mygildan.com/store/us/browse/productDetailsPage.jsp?productId=2000">Ultra Cotton "Classic Fit" shirt</a>.</li>
 
  <li>The Women's Semi-Fitted option is the <a href="http://www.mygildan.com/store/us/browse/productDetailsPage.jsp?productId=5000L">Heavy Cotton Semi-Fitted Ladies' shirt</a></li>
 
  <li>The Women's Relaxed Fit option is the <a href="http://www.mygildan.com/store/us/browse/productDetailsPage.jsp?productId=2000L">Ultra Cotton "Classic Fit" Ladies' shirt</a></li>
 
</ul>
 

	
 
<table class="table table-striped">
 
  <tbody><tr>
 
    <th></th>
 
    <th colspan="2">XS</th>
 
    <th colspan="2">S</th>
 
    <th colspan="2">M</th>
 
    <th colspan="2">L</th>
 
    <th colspan="2">XL</th>
 
    <th colspan="2">2XL</th>
 
    <th colspan="2">3XL</th>
 
    <th colspan="2">5XL</th>
 
</tr>
 
<tr>
 
    <th></th>
 
    <th>W</th>
 
    <th>L</th>
 
    <th>W</th>
 
    <th>L</th>
 
    <th>W</th>
 
    <th>L</th>
 
    <th>W</th>
 
    <th>L</th>
 
    <th>W</th>
 
    <th>L</th>
 
    <th>W</th>
 
    <th>L</th>
 
    <th>W</th>
 
    <th>L</th>
 
    <th>W</th>
 
    <th>L</th>
 
</tr>
 
<tr>
 
    <td>Men's / Straight Cut</td>
 
    <td>-</td>
 
    <td>-</td>
 
    <td>18</td>
 
    <td>28</td>
 
    <td>20</td>
 
    <td>29</td>
 
    <td>22</td>
 
    <td>30</td>
 
    <td>24</td>
 
    <td>31</td>
 
    <td>26</td>
 
    <td>32</td>
 
    <td>28</td>
 
    <td>33</td>
 
    <td>32</td>
 
    <td>35</td>
 
</tr>
 
<tr>
 
    <td>Women's <br> Semi-Fitted</td>
 
    <td>-</td>
 
    <td>-</td>
 
    <td>17&frac14;</td>
 
    <td>25&frac12;</td>
 
    <td>19&frac14;</td>
 
    <td>26</td>
 
    <td>21&frac14;</td>
 
    <td>27</td>
 
    <td>23&frac14;</td>
 
    <td>28</td>
 
    <td>25&frac14;</td>
 
    <td>28&frac12;</td>
 
    <td>27&frac14;</td>
 
    <td>29</td>
 
    <td>-</td>
 
    <td>-</td>
 
</tr>
 
<tr>
 
    <td>Women's <br> Relaxed Fit</td>
 
    <td>16</td>
 
    <td>23&frac12;</td>
 
    <td>18</td>
 
    <td>25</td>
 
    <td>20</td>
 
    <td>26</td>
 
    <td>22</td>
 
    <td>27</td>
 
    <td>24</td>
 
    <td>28</td>
 
    <td>26</td>
 
    <td>29</td>
 
    <td>28</td>
 
    <td>30</td>
 
    <td>-</td>
 
    <td>-</td>
 
</tr>
 
</tbody></table>
 

	
 

	
 
{% endblock %}
pinaxcon/templates/static_pages/homepage.html
Show inline comments
...
 
@@ -28,7 +28,6 @@
 

	
 
          <h4>
 
            December 2 &amp; 3, 2017<br/>
 
            Talk submissions close September 29
 
          </h4>
 
        </div>
 
        <div class="col-md-4 col-md-offset-2 email-signup-panel">
...
 
@@ -64,7 +63,6 @@
 

	
 
    <div class="container homepage-block-footer">
 
      <div>
 
        <a class="btn btn-primary btn-lg" href="/dashboard">Submit a Proposal</a>
 
        <a class="btn btn-default btn-lg " href="https://twitter.com/northbaypython">Twitter</a>
 
        <a class="btn btn-default btn-lg" href="https://facebook.com/northbaypython">Facebook</a>
 
      </div>
...
 
@@ -81,17 +79,19 @@
 
      <ul>
 
        <li>An historic venue with countless restaurants and coffee shops in walking distance</li>
 
        <li>World-famous craft food and drink producers on your doorstep</li>
 
        <li>Charming small-town hotels, as close as one block away</li>
 
        <li>Charming <a href="/attend/hotels">small-town hotels</a>, as close as one block away</li>
 
      </ul>
 

	
 
      <p>&hellip; and it's only an hour away from San Francisco (on a good day).</p>
 
      <p>&hellip; and it's <a href="/attend/travel">only an hour away from San Francisco</a> (on a good day).</p>
 
    </div>
 

	
 
    <div class="homepage-block-footer full-width">
 
      <div class="container">
 
        <div class="row">
 
          <div class="btn-group col-md-4">
 
            <a class="btn btn-lg btn-primary btn-shadow" href="/about/north-bay-python">Learn More</a>
 
          <div class="col-md-4">
 
            <a class="btn btn-lg btn-primary btn-shadow" href="/about/petaluma">Learn More</a>
 
            <a class="btn btn-lg btn-info" href="/attend/hotels">Hotels</a>
 
            <a class="btn btn-lg btn-info" href="/attend/travel">Travel</a>
 
          </div>
 

	
 
          <div class="col-md-8 text-right photo-attribution">
pinaxcon/templates/static_pages/news.html
Show inline comments
...
 
@@ -10,6 +10,29 @@
 

	
 
{% block content %}
 

	
 
<a name="3"></a>
 
<h2>Tickets now on sale for North Bay Python 2017</h2>
 

	
 
<p><span class="date">Tuesday, October 3, 2017</span>&mdash;We are excited to announce that <a href="https://2017.northbaypython.org/tickets">tickets are now on sale</a> for North Bay Python 2017. With just two months until the conference we have a few key dates coming up:</p>
 

	
 
<ul>
 
  <li><a href="https://2017.northbaypython.org/tickets">Tickets</a> are available at a discount until Friday, October 20.</li>
 
  <li><a href="https://2017.northbaypython.org/attend/hotels">Hotel rooms</a> are available at a discount until Wednesday, November 1.</li>
 
  <li><a href="https://2017.northbaypython.org/attend/tshirts">T-shirts</a> can be ordered until Tuesday, November 7.</li>
 
</ul>
 

	
 
<p>Can't afford a ticket? Please email <a href="mailto:spam@northbaypython.org">spam@northbaypython.org</a>. We'll enthusiastically waive ticket fees for people who ask.</p>
 

	
 
<p>Need to get approval from your manager to attend North Bay Python 2017? We've outlined the <a href="https://2017.northbaypython.org/attend/business-case">business case</a> to make it clear that North Bay Python is a wise investment.</p>
 

	
 
<p>We've prepared a basic <a href="https://2017.northbaypython.org/about/petaluma">travel guide</a> with lodging and travel information. This resource will grow to include local restaurants and other amenities.</p>
 

	
 
<p>Currently we're reviewing 117 proposals from 82 people interested in speaking at North Bay Python 2017. We are grateful to the communities and individuals for: sharing the news, encouraging others, mentoring prospective speakers, crafting proposals, and reviewing those proposals.</p>
 

	
 
<p>Our inaugural event is going to have a fantastic program. We can't wait to announce our keynote speakers and program schedule!</p>
 

	
 
<p><a href="https://2017.northbaypython.org/tickets">Buy tickets</a> and <a href="https://2017.northbaypython.org/attend/hotels">book hotel rooms</a> soon to get the best rates.</p>
 

	
 
<a name="2"></a>
 
<h2>Reflecting the Bay in the North Bay Python 2017 speaker lineup</h2>
 

	
...
 
@@ -43,25 +66,25 @@
 
<a name="1"></a>
 
<h2>Now accepting talk proposals for North Bay Python 2017</h2>
 

	
 
<p><span class="date">Monday, August 21, 2017</span>&mdash;The North Bay Python team is excited to announce that the <a href="/program/call-for-proposals" title="North Bay Python Call for Proposals">call for proposals</a> (CFP) is now open! We are seeking speakers of all experience levels to contribute to our inaugural conference. The CFP will close on September 29, 2017.</p>
 
<p><span class="date">Monday, August 21, 2017</span>&mdash;The North Bay Python team is excited to announce that the <a href="https://2017.northbaypython.org/program/call-for-proposals">call for proposals</a> (CFP) is now open! We are seeking speakers of all experience levels to contribute to our inaugural conference. The CFP will close on September 29, 2017.</p>
 

	
 
<p>North Bay Python is a single-track event featuring two days of presentations by members of the community. The vast majority of the conference program will come from people who propose talks in our CFP process. Whether you use Python professionally, as a hobbyist, or are just excited about Python or programming and open source, we'd love to hear from you.</p>
 

	
 
<p>Our program committee, which is responsible for reviewing proposals, is interested in building a program that reflects the diversity of people who are using Python. Never given a presentation before but excited to share? We're here to help you craft a proposal and can refer you to quality resources for making your first conference talk. Not sure what to talk about, but interested in trying? We've got ideas for presentations we'd love to see and we're happy to share them with you!</p>
 

	
 
<p>In order to ensure a balanced program, we are proactively doing outreach to new and experienced speakers alike. We are also including a blind review phase in our <a href="/program/selection-process" title="North Bay Python proposal selection process">selection process</a> in order to combat bias. Our goal is to have no less than 33% of our speakers be not-men, ideally 50%, and to reflect the racial diversity of United States and Bay Area demographics.</p>
 
<p>In order to ensure a balanced program, we are proactively doing outreach to new and experienced speakers alike. We are also including a blind review phase in our <a href="https://2017.northbaypython.org/program/selection-process">selection process</a> in order to combat bias. Our goal is to have no less than 33% of our speakers be not-men, ideally 50%, and to reflect the racial diversity of United States and Bay Area demographics.</p>
 

	
 
<p>Feel free to reach out with any questions, comments, or ideas you have. You can find us on <a href="https://twitter.com/northbaypython" title="North Bay Python on Twitter">Twitter</a>, <a href="https://facebook.com/northbaypython" title="North Bay Python on Facebook">Facebook</a>, and <a href="https://webchat.freenode.net/?channels=%23nbpy" title="IRC Web Client for #nbpy Channel on Freenode">IRC</a>, or you can <a href="mailto:program@northbaypython.org" title="program@northbaypython.org">email us</a>. Please, get started today! The <a href="/program/call-for-proposals" title="North Bay Python Call for Proposals">call for proposals</a> closes on September 29, 2017.</p>
 
<p>Feel free to reach out with any questions, comments, or ideas you have. You can find us on <a href="https://twitter.com/northbaypython">Twitter</a>, <a href="https://facebook.com/northbaypython">Facebook</a>, and <a href="https://webchat.freenode.net/?channels=%23nbpy">IRC</a>, or you can <a href="mailto:program@northbaypython.org">email us</a>. Please, get started today! The <a href="https://2017.northbaypython.org/program/call-for-proposals">call for proposals</a> closes on September 29, 2017.</p>
 

	
 
<a name="0"></a>
 
<h2>North Bay Python joins Software Freedom Conservancy</h2>
 

	
 
<p><span class="date">Wednesday, August 16, 2017</span>&mdash;We are proud to announce that North Bay Python is now a member project of <a href="https://sfconservancy.org" title="Software Freedom Conservancy">Software Freedom Conservancy</a>, a 501(c)(3) charity dedicated to ethical technology and the development and promotion free and open source software. Conservancy will act as our fiscal sponsor, allowing our team to operate without managing our own corporate structure and administrative services.</p>
 
<p><span class="date">Wednesday, August 16, 2017</span>&mdash;We are proud to announce that North Bay Python is now a member project of <a href="https://sfconservancy.org">Software Freedom Conservancy</a>, a 501(c)(3) charity dedicated to ethical technology and the development and promotion free and open source software. Conservancy will act as our fiscal sponsor, allowing our team to operate without managing our own corporate structure and administrative services.</p>
 

	
 
<p>Conservancy is home to many popular <a href="https://sfconservancy.org/projects/current/" title="Current Member Projects of the Software Freedom Conservancy">free and open source software projects</a>, like <a href="http://www.seleniumhq.org/" title="Selenium">Selenium</a>, <a href="https://pypy.org/" title="PyPy">PyPy</a>, <a href="https://www.phpmyadmin.net/" title="phpMyAdmin">phpMyAdmin</a>, <a href="https://twistedmatrix.com/trac/" title="Twisted">Twisted</a>, and <a href="https://www.gnome.org/outreachy/" title="Outreachy">Outreachy</a>, some of which run their own events. North Bay Python has the distinct honor of being the first member project that is exclusively focused on organizing community events.</p>
 
<p>Conservancy is home to many popular <a href="https://sfconservancy.org/projects/current/">free and open source software projects</a>, like <a href="http://www.seleniumhq.org/">Selenium</a>, <a href="https://pypy.org/">PyPy</a>, <a href="https://www.phpmyadmin.net/">phpMyAdmin</a>, <a href="https://twistedmatrix.com/trac/">Twisted</a>, and <a href="https://www.gnome.org/outreachy/">Outreachy</a>, some of which run their own events. North Bay Python has the distinct honor of being the first member project that is exclusively focused on organizing community events.</p>
 

	
 
<p>We couldn't be more excited. We're celebrating by donating five free tickets to Outreachy participants and will be promoting member projects relevant to the Python community at the conference. Interested Outreachy alums (past or present) should <a href="mailto:outreach@northbaypython.org" title="outreach@northbaypython.org">contact us</a>. We'll also have discounted tickets available for active financial supporters of Software Freedom Conservancy.</p>
 
<p>We couldn't be more excited. We're celebrating by donating five free tickets to Outreachy participants and will be promoting member projects relevant to the Python community at the conference. Interested Outreachy alums (past or present) should <a href="mailto:outreach@northbaypython.org">contact us</a>. We'll also have discounted tickets available for active financial supporters of Software Freedom Conservancy.</p>
 

	
 
<p>We look forward to working with Conservancy to advance software freedom and expand the community of Python developers. If this is the first time you've heard of Conservancy, we encourage you to check out <a href="https://sfconservancy.org" title="Software Freedom Conservancy">their website</a> and give them your support.</p>
 
<p>We look forward to working with Conservancy to advance software freedom and expand the community of Python developers. If this is the first time you've heard of Conservancy, we encourage you to check out <a href="https://sfconservancy.org">their website</a> and give them your support.</p>
 

	
 
{% endblock %}
pinaxcon/templates/static_pages/program/events.html
Show inline comments
 
new file 100644
 
{% extends "page_with_title_and_lede.html" %}
 

	
 
{% load i18n %}
 

	
 
{% block head_title %}Events{% endblock %}
 

	
 
{% block heading %}Events{% endblock %}
 

	
 
{% block body_class %}program{% endblock %}
 

	
 
{% block lede %}
 
  North Bay Python 2017 is coming, and with it: more Python. We'll add satellite events and more to this page as details are available.
 
{% endblock %}
 

	
 

	
 
{% block content %}
 

	
 
<h2>A Taste of Python and Django<br/>
 
  <small>October 24, 2017</small></h2>
 

	
 
<p>A pre-conference event with local meetup group, Web &amp; Interactive Media Professionals (WIMP). At least three of the North Bay Python organizers will be present at this potluck-style event at Santa Rosa Junior College. <a href="https://www.facebook.com/events/1936385509950665/">Find more information and join us!</a></p>
 

	
 
<h2>Speaker Training<br/>
 
  <small>December 1, 2017</small></h2>
 

	
 
<p>We are running a speaker training the day before the conference. Everyone who is accepted to speak at the conference is invited to attend. <a href="mailto:spam@northbaypython.org">Let us know</a> if you're interested in attending, we may have seats available.</p>
 

	
 
<h2>North Bay Python 2017<br/>
 
  <small>December 2-3, 2017</small></h2>
 

	
 
<p>This year's main event will run from 10:00am to 6:00pm each day with check-in starting at 9:00am on Saturday. Our program schedule will be released later this month. You can <a href="/tickets">buy your ticket today</a>!</p>
 

	
 
{% endblock %}
pinaxcon/templates/static_pages/sponsors/donate.html