Home

Powered by Django

Customizing a Django RSS Feed

Date: Mar 09, 2015

The Framework: Django 1.3 (not my choice!)

The Mission: Create an RSS feed that includes an extra field for full story content, plus a few additional fields for images

I know. It's 2015 and we're still on 1.3. But the changes to Django syndication since 1.3 haven't been that dramatic, so you might find this useful if you're in the same boat.

ADDING CUSTOM FIELDS

Let's start with the methods needed to add some custom content to a <content:encoded> element.

The Django feed library comes with a set of standard elements for which you must define the content: <title>, <link>, and <description> for the feed, and then of course <title>, <link>, and <description> for individual feed items.

In our use case, we have a feed containing a list of news stories. We're already sending a truncated version of each story's content to <description>, but we want to add an additional field - <content:encoded> - to return the story's full content.

To add an additional element (or two or three), there are a few places you'll need to update - two (possibly three) standard feed methods and whatever custom method(s) you need to populate the new elements.

In this code sample, follow the trail from item_extra_kwargs() to item_your_custom_field() to add_item_elements().

from django.contrib.syndication.views import Feed
from django.utils.feedgenerator import Rss201rev2Feed

class ExtendedRSSFeed(Rss201rev2Feed):
    """
    Create a type of RSS feed that has content:encoded elements.
    """
    def root_attributes(self):
        attrs = super(ExtendedRSSFeed, self).root_attributes()
        # Because I'm adding a <content:encoded> field, I first need to declare
        # the content namespace. For more information on how this works, check
        # out: http://validator.w3.org/feed/docs/howto/declare_namespaces.html
        attrs['xmlns:content'] = 'http://purl.org/rss/1.0/modules/content/'
        return attrs
    
    def add_item_elements(self, handler, item):
        super(ExtendedRSSFeed, self).add_item_elements(handler, item)

        # 'content_encoded' is added to the item below, in item_extra_kwargs()
        # It's populated in item_your_custom_field(). Here we're creating
        # the <content:encoded> element and adding it to our feed xml
        if item['content_encoded'] is not None:
            handler.addQuickElement(u'content_encoded', item['content_encoded'])

    ...

class YourFeed(Feed):
    feed_type = ExtendedRSSFeed

    ....

    def item_extra_kwargs(self, item):
        # This is probably the first place you'll add a reference to the new
        # content. Start by superclassing the method, then append your
        # extra field and call the method you'll use to populate it.
        extra = super(YourFeed, self).item_extra_kwargs(item)
        extra.update({'content_encoded': self.item_your_custom_field(item)})
        return extra
    
    def item_your_custom_field(self, item):
        # This is your custom method for populating the field.
        # Name it whatever you want, so long as it matches what
        # you're calling from item_extra_kwargs().
        # What you do here is entirely dependent on what your
        # system looks like. I'm using a simple queryset example,
        # but this is not to be taken literally.
        obj_id = item['my_item_id']
        query_obj = MyStoryModel.objects.get(pk=obj_id)
        full_text = query_obj['full_story_content']
        return full_text

This generates a feed that looks something like this:

<?xml version="1.0" encoding="utf-8"?> <rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0"> <channel> <title>News List</title> <link>http://www.example.com/</link> <description>List Description</description> <item> <title>News List Story 1</title> <link>http://www.example.com/news/story-one/</link> <description>This is the story description.</description> <content:encoded>This is the story description. This is the full content of the story. (Not a very exciting story, I know.)</content:encoded> </item> </channel> </rss>

My actual use case called for me to extend from a feed that already existed, leaving that original feed intact and only including the new element in the new feed. Here's how you'd do that:

class YourFeed(Feed):
    feed_type = ExtendedRSSFeed

    ....

    def item_extra_kwargs(self, item):
        extra = super(YourFeed, self).item_extra_kwargs(item)
        extra.update({'content_encoded': self.item_your_custom_field(item)})
        return extra
    
    def item_your_custom_field(self, item):
        return None

class YourNewFeed(YourFeed):

    def item_your_custom_field(self, item):
        ...
        return full_text

So in the original feed, 'content_encoded' comes back as None and <content:encoded> never appears. It is only generated for the new feed.

CDATA?

The customer requesting this new feed actually asked for html wrapped in a CDATA section. I never did figure out how to do that with the Django syndicator alone - the CDATA tag always came out encoded, there didn't seem to be any way around that. And every blog post I found lead me back to this old bug ticket - https://code.djangoproject.com/ticket/15936 - which suggests just ditching the CDATA section and letting Django handle the encoding. I tried that, but it didn't pass the W3C feed validator - more on that later.

CUSTOM TEMPLATES

One of the things we tried along the way was a custom template for the CDATA content. That didn't work for creating a CDATA section, as ultimately there was no way to prevent the tag from being encoded. But I didn't find many clear posts about how to do this so I thought I'd share an outline of the attempt here:

from django.template import loader, Context, TemplateDoesNotExist

...

    def item_extra_kwargs(self, item):
        extra = super(ListDetailRSS, self).item_extra_kwargs(item)

        # Define a template - give it any name, the one below is just an example.
        # The path will obviously depend on your settings.
        content_encoded_template = 'feeds/list_detail_content_encoded.html'
        try:
            # Use the Django template loader to get the template
            content_encoded_tmp = loader.get_template(content_encoded_template)
            # Set the field value as template context
            content_encoded = content_encoded_tmp.render(
                        Context({'myobj': self.item_your_custom_field(item)}))
            # Then update your extra kwargs with the rendered template
            # instead of the original value returned from your custom method
            extra.update({'content_encoded': content_encoded})
        except TemplateDoesNotExist:
            # And if you don't have a template, just use the content as
            # returned from your custom method
            extra.update({'content_encoded': self.item_your_custom_field(item)})

    return extra

Your template can be as simple as this:

    {{ myobj }}

This can be useful if you want to customize your value by wrapping some text around it or maybe apply template filters before it's rendered.

WRAPPING ELEMENTS INSIDE OTHER ELEMENTS

Our new <content:encoded> element is supposed to have a few other fields inside it. What I'm showing you here ultimately didn't work for us (see the encoding section below), but I did learn a thing or two about how to wrap elements inside other elements in ways that aren't covered in the Django documentation (I should get on adding that, right?).

    def add_item_elements(self, handler, item):
        super(ExtendedRSSFeed, self).add_item_elements(handler, item)

        if item['content_encoded'] is not None:
            # <content:encoded> is going to wrap around some other elements,
            # so instead of using handler.addQuickElement() we're going to
            # use startElement() (and then end it later)
            handler.startElement(u"content:encoded", {})

            # handler.characters() fills in content between the tags, e.g.:
            # <content:encoded>This is where the content goes.</content:encoded>
            handler.characters(item['content_encoded'])

            # And close the element, ba-bam.
            handler.endElement(u"content:encoded")

If you wanted to apply attributes to the element itself, that empty dict you set at startElement() would look like this instead:

    if item['content_encoded'] is not None:
        handler.startElement(u"content:encoded", {'my-attribute': 'my-value'})

And here's the wrapping around other elements bit:

    if item['content_encoded'] is not None:
        handler.startElement(u"content:encoded", {})
        handler.characters(item['content_encoded'])

        # Suppose we have a photo to go along with this story
        if item['media'] is not None:

            handler.startElement(u'figure', {'type': 'image/jpeg'})
            handler.startElement(u'image', {
                'src': item['media']['src'],
                'caption': item['media']['caption']
            })
            handler.endElement(u'image')
            handler.endElement(u'figure')

        handler.endElement(u"content:encoded")

ENCODING - OR, DOUBLE ENCODING

Back to that old bug ticket. We ultimately decided to follow the sage advice to forget about CDATA, even though the suggested code didn't work exactly as described (whether that's because of our old version of Django, or our version customizations, I don't know, but I never had time to research it).

Instead, we had to ... double encode? Or rather, escape, then let Django encoding do its thing.

After all that work to wrap elements one inside the other, our feed still wasn't validating. So instead of creating them as elements, we just converted the tags to strings:

    if item['content_encoded'] is not None:
        handler.startElement(u"content:encoded", {})
        handler.characters(item['content_encoded'])

        if item['media'] is not None:
            figure = '<figure type="image/jpeg">'
            figure += '<image src="%s" caption="%"></image>' % \
                    (item['media']['src'], item['media']['caption'])
            figure += '</image></figure>'
            # Don't forget to stick that string in the middle of
            # the <content:encoded> element:
            handler.characters(figure)

        handler.endElement(u"content:encoded")

<content:encoded> &lt;p&gt;&amp;lt;p&amp;gt;This is the story description.&amp;lt;/p&amp;gt; &amp;lt;p&amp;gt;This is the full content of the story.&amp;lt;/p&amp;gt; &amp;lt;p&amp;gt;(Not a very exciting story, I know.)&amp;lt;/p&amp;gt;&lt;/p&gt; &amp;lt;figure type="image/jpeg"&amp;gt; &amp;lt;image src="/media/photos/2014/05/07/050714.jpg" caption="Test Photo"&amp;gt; &amp;lt;/figure&amp;gt; </content:encoded>

Ugly, yes, but it almost worked. At least it failed in a different way.

After some trial and error, I found that ultimately I had to do some xml-specific escaping. I wound up using a method out of SAX utilities, applied it to the story content as it was being returned from my custom method, and also to the string for that <figure> tag inside <content:encoded>.

from xml.sax.saxutils import escape

...

    def add_item_elements(self, handler, item):

        ...

        if item['content_encoded'] is not None:
            handler.startElement(u"content:encoded", {})
            handler.characters(item['content_encoded'])

            # Suppose we have a photo to go along with this story
            if item['media'] is not None:

            figure = '<figure type="image/jpeg">'
                ...
                handler.characters(escape(figure))

            handler.endElement(u"content:encoded")

    ...

class YourNewFeed(YourFeed):

    def item_your_custom_field(self, item):
        ...
        return escape(full_text)

What that returns looks slightly uglier. But guess what? It validates.

<content:encoded> &amp;lt;p&amp;gt;&amp;amp;lt;p&amp;amp;gt;This is the story description.&amp;amp;lt;/p&amp;amp;gt; &amp;amp;lt;p&amp;amp;gt;This is the full content of the story.&amp;amp;lt;/p&amp;amp;gt; &amp;amp;lt;p&amp;amp;gt;(Not a very exciting story, I know.)&amp;amp;lt;/p&amp;amp;gt;&amp;lt;/p&amp;gt; &amp;lt;figure type="image/jpeg"&amp;gt; &amp;lt;image src="/media/photos/2014/05/07/050714.jpg" caption="Test Photo"&amp;gt; &amp;lt;/figure&amp;gt; </content:encoded>

THE COMPLETE PICTURE

from xml.sax.saxutils import escape

from django.contrib.syndication.views import Feed
from django.utils.feedgenerator import Rss201rev2Feed

class ExtendedRSSFeed(Rss201rev2Feed):

    def root_attributes(self):
        attrs = super(ExtendedRSSFeed, self).root_attributes()
        attrs['xmlns:content'] = 'http://purl.org/rss/1.0/modules/content/'
        return attrs
    
    def add_item_elements(self, handler, item):
        super(ExtendedRSSFeed, self).add_item_elements(handler, item)

        if item['content_encoded'] is not None:

            handler.startElement(u"content:encoded", {})
            handler.characters(item['content_encoded'])

            if item['media'] is not None:
                figure = '<figure type="image/jpeg">'
                figure += '<image src="%s" caption="%"></image>' % \
                        (item['media']['src'], item['media']['caption'])
                figure += '</image></figure>'
                handler.characters(escape(figure))

            handler.endElement(u"content:encoded")

    ...

class YourFeed(Feed):
    feed_type = ExtendedRSSFeed

    ....

    def item_extra_kwargs(self, item):
        extra = super(YourFeed, self).item_extra_kwargs(item)
        extra.update({'content_encoded': self.item_your_custom_field(item)})
        extra.update({'media': self.item_your_custom_media_field(item)})
        return extra
    
    def item_your_custom_field(self, item):
        return None

    def item_your_custom_media_field(self, item):
        return None

class YourNewFeed(YourFeed):

    def item_your_custom_field(self, item):
        obj_id = item['my_item_id']
        query_obj = MyStoryModel.objects.get(pk=obj_id)
        full_text = query_obj['full_story_content']
        return escape(full_text)

    def item_your_custom_media_field(self, item):
        obj_id = item['my_item_id']
        query_obj = MyStoryModel.objects.get(pk=obj_id)
        photo = query_obj['photo']['url']
        caption = query_obj['photo']['caption']
        return {'src': photo, 'caption': caption}

<?xml version="1.0" encoding="utf-8"?> <rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0"> <channel> <title>News List</title> <link>http://www.example.com/</link> <description>List Description</description> <atom:link href="http://www.example.com/" rel="self"></atom:link> <item> <guid isPermaLink="false">http://www.example.com/guid/</guid> <title>News List Story 1</title> <link>http://www.example.com/news/story-one/</link> <description>This is the story description.</description> <content:encoded> &amp;lt;p&amp;gt;&amp;amp;lt;p&amp;amp;gt;This is the story description.&amp;amp;lt;/p&amp;amp;gt; &amp;amp;lt;p&amp;amp;gt;This is the full content of the story.&amp;amp;lt;/p&amp;amp;gt; &amp;amp;lt;p&amp;amp;gt;(Not a very exciting story, I know.)&amp;amp;lt;/p&amp;amp;gt;&amp;lt;/p&amp;gt; &amp;lt;figure type="image/jpeg"&amp;gt; &amp;lt;image src="/media/photos/2014/05/07/050714.jpg" caption="Test Photo"&amp;gt; &amp;lt;/figure&amp;gt; </content:encoded> </item> </channel> </rss>

Powered by Django

PyCon 2014

Date: Apr 27, 2014

I just want to pop in here briefly and let everyone know that PyCon 2014 went well! It's a few weeks in the past already, but I've been busy with a lot of follow-up projects ever since I got back.

A few people remarked - and I agree - that the more years you come to PyCon, the fewer people you get to see each time because you become so much more involved in volunteering. That was definitely true of 2014. Katie Cunningham and I did a talk on Friday, the first day of the conference, then spent that Saturday and Sunday in the classroom.

With all that going on, I was lucky that I got to see anyone at all. I managed to stop at the PyLadies booth for a few minutes, but sadly missed out on the camaraderie of the feminist hackerspace. Aside from my own, I only made time for two other talks. Noah Kantrowitz was enlightening as always with his Application Deployment State of the Onion.

But if you only watch one video from this year's PyCon, make it this one:

It's Dangerous to Go Alone: Battling the Invisible Monsters in Tech

Every programmer I know, myself definitely included, could use some of Julie Pagano's wise words. Her talk brought me to tears, and I'm pretty sure I was not the only one.

This year, instead of being partitioned by age group, the two days of Young Coders classes were split by spoken language - English on the first day and French on the second day. We had two terrific local teachers - David Cormier and Davin Baragiotta - working with the kids on the second day. It was fascinating seeing our teaching materials translated and taught in another language! And Davin and David are terrific teachers - they both brought so much energy and enthusiasm to the kids.

The talk was the hardest part of the conference for me. For as long as I've been going to PyCon, I've sworn that I would never take that stage - I was far too shy and crippled by stage fright. But I got over it and I did it. The conference organizers made the experience really pleasant (thanks so much to Diana, Doug, Tom, and everyone else who helped out!), and I got a lot of support from friends who've been encouraging me to take this leap for years. To anyone else trying to conquer a fear of public speaking, I would say that the most important thing is to really know your material - with that knowing comes confidence.

So here it is: "The Young Coder: Let's Learn Python":

(Also available on PyVideo: http://pyvideo.org/video/2570/the-young-coder-lets-learn-python)

Powered by Django

A computer science classroom project without a name

Date: Sep 17, 2013

A little over a month ago now, just as the new school year was about to begin, I had the privilege of attending a meeting of the local chapter of Computer Science Teachers Association here in Austin. I didn't really have any plans - my goal was just to get to know some of these local teachers and see if there was a way that I could help. Help how? I had no idea.

But as we got to talking, it became clear that what would be most welcome - at least for now - would be to get developers into the classrooms, to have them talk to students about their careers and maybe get involved directly, through mentoring and teaching.

And so the gears in my head started turning.

Last year, I volunteered with a local program called Central Texas Discover Engineering. It's a terrific way to reach out to schools and promote STEM: Through CTDE, science professionals can sign up, get paired with an elementary school teacher/classroom, and make plans for a school visit. This past spring, a few of us from PyLadies went to visit a 5th grade class in south Austin to give a talk about how we use programming in our jobs. The kids were so curious and enthusiastic - imagine how receptive a classroom of aspiring programmers would have been?

CTDE has more of a general science focus, but I wanted to adopt their model, so instead I'm working on building a roster of developers that are available specifically for visiting with Computer Science students in middle and high schools. The way I'm envisioning it, these classroom visits could just mean talking to students about what software development careers are like and what kinds of things you need to learn to get there. They might also involve some teaching, one-on-one mentoring, or extras such as helping to run an after-school computer club, if we find developer volunteers who are interested in doing those things.

And now I'm in a little bit over my head, but loving every minute of it. This is the first time I've ever attempted to put together a program like this. So far, we've gotten a huge response from the handful of user groups we've reached out to. Austin's developer community gets it - they're lining up to get into the classrooms and help kids. It's been a little slower getting the word out to teachers, but that is starting to take off as well. My hope is that signups on both sides will continue, so that Austin developers are continuing to work with area educators throughout the school year.

As teachers and developers have signed on, I've generated welcome emails, but the first letters matching volunteers to school just went out today. Volunteers are being asked to contact the teachers, but both sides are getting information about each other: teachers learn about the specialties and expertise of the volunteers they've been matched with, and volunteers get a little information about the classes they expect to be visiting - how big the classes are, what age group, what languages they're working with. It's up to the teacher and volunteer to negotiate what the content of the classroom visit will be. We're suggesting things like career talks, coding demonstrations, and mentoring, but these visits are really open to whatever the teacher and developer agree on.

In the meantime, I'm hoping to focus on getting a web site together - right now, this whole project consists of a couple of Google Drive forms and a spreadsheet. Oh, and a couple of scripts to generate the emails.

My plan is to harness the brain power of our local PyLadies chapter and put together a team to help with a web site. We just need a handful of features - separate signups for teachers and developers, a page of presentation ideas and activity resources that developers can use when planning their visits, some automation for the teacher/volunteer matching, and automation for the assortment of emails that have to be sent.

There is one thing holding us back - the project does not have a name. So if you know how to reach me and you have an idea, please let me know.

I'm really looking forward to seeing what an impact this program makes on local computer science classrooms this year. We're keeping it simple for 2013-2014, but if it's a success, we might expand and do some different things for the next school year.

Once the first classroom visits begin, I'll update on how well it's all working out.

Powered by Django

An open letter to tech conference organizers

Date: May 31, 2013

Make that "conference organizers who are interested in increasing diversity among your attendees, or in your community, or (hopefully), both".

Take what I'm about to suggest with a grain of salt. I'm a programmer and a woman who's been going to conferences for several years now. I have a ton of experience as an attendee, a little as a speaker and teacher, but I'm not privy to the specific challenges that an organizer faces. That said, I've observed a few things over the years, and I have some ideas that may help.

  1. Have a Code of Conduct.

    Have in place some declaration of how you expect attendees to behave towards one another. It doesn't matter what you call it - a Code of Conduct, an anti-harassment policy. The point is to define, in clear language, what you consider to be offensive behavior, and to let attendees know that it won't be tolerated.

    I'm not going to go into why you need a Code of Conduct - that argument has already been made by more eloquent writers than I, but if you still need convincing, I'd suggest taking a look at Jacob Kaplan-Moss' 2011 post, Why conferences need a code of conduct.

    Not everyone agrees on the finer points of what should be covered in a code of conduct, but I think that there are some general principles that are widely acknowledged as necessary. A good starting point is this sample conference anti-harassment policy developed by the Ada Initiative, released under a Creative Commons Zero license and hosted on the Geek Feminism Wiki.

  2. Tell me how to use it.

    Don't forget to address this prominently in your policy - make clear how you want attendees to report incidents if they occur. Give us a clear point of contact - either with a single staff member, or better yet, with anyone on the conference staff - and make sure everyone knows what form follow-up will take. If it's not clear to me how I should handle a harassment case, I'm likely to take matters into my own hands - tweet about it, blog about it, badmouth you or your conference. Or I may not report anything at all, which means that bad behavior goes unaddressed and someone else will likely have to deal with it down the line.

  3. Make sure I can find it.

    If I'm thinking about registering for your conference, I should be able to check it out first. That means getting at least a general idea of what the content will be - AND what your anti-harassment policy is. Don't hide it, don't make it impossible to find just because it doesn't fit neatly with your conference site's pretty design. Don't bury it in the registration process - if I can't see it beforehand, I might not be registering in the first place.

    • Good: Make sure the policy has its own page, and that there's a link to it from your FAQ or About page.
    • Better: Give it its own link, placed somewhere in a footer, or along with other general information sections such as an FAQ.
    • Best: Display the link prominently in your site's main navigation.

  4. Identify your staff members.

    If your response process involves having attendees contact a staff member, make sure we can tell who your staff members are. Nothing says "we're here to help" better than a conference staff that makes itself easy to find. If it's practical, maybe you can introduce staff during the keynote or opening remarks. Be sure that staff members have badges that look different from those issued to conference attendees - if it's not practical to order separate badges, use ribbons or stickers as an indicator. And if you can swing it, get special shirts of the same color - I'm at JSConf this week, and the conference runners have stood out in every crowd, unmistakable in their bright teal t-shirts. Now that's what I'm talking about.

Powered by Django

My weird health issues

Date: May 16, 2013

If we're connected on Facebook, you've probably already seen bits and pieces of this story. Is it weird to be talking about my health problems on what is ostensibly a tech blog? Maybe. But there are enough people who have been curious that I thought I'd better explain what's going on. I also don't want it to be a big surprise when I step back a little from organizing and teaching this summer. And when I don't end up submitting all the talk proposals I've been so excited about, it's not out of fear - I just need to scale back my travel plans for the foreseeable future.

Back in November, not long after I moved to Austin, I started experiencing some symptoms - muscle fatigue, dizziness, irregular heartbeat and shortness of breath. They were mild at first, but by January had intensified to the point that I was experiencing them daily, and by February it was almost around the clock. It feels like a blood sugar crash, or caffeine shakes, except that it can go on for hours and hours.

This isn't a case of burning out: I've just started a new job that I'm really excited about. And I'm on fire with ideas - workshops I want to teach, programs I want to start, presentations I want to give, all kinds of things I want to contribute back to the Python community.

It's not about forgetting to take care of myself either - I'm doing all the right things, they just don't seem to be helping. I've been eating a healthy diet. No caffeine, no junk food, almost no sugar, lots of fresh fruits and vegetables. I stopped working out for a little while, but I'm back in the gym at least three days a week now (I work out around lunchtime, the only time I have the energy).

I don't want to go to into too many details, but I've seen several different doctors over the last few months and had done just about every test known to man (have I mentioned how squeamish I am about having blood drawn?). It's not thyroid, hypoglycemia, celiac, B-12 deficiency, or anything like that. The only thing we've found conclusively is that I'm suffering from a heart condition that runs in my family. It's not dangerous, but it can be very painful.

I am taking medication for that, but that's barely put a dent in the symptoms. By the end of most days my energy is completely sapped, and I'm too exhausted to work on anything else. As far as anyone can tell, the stuff that's going on with my heart is annoying, uncomfortable, and tiring much of the time, but it's not at all life-threatening. Still, it's frightening to feel so weak and fatigued every night and have no idea why. I don't know how to make myself feel better, and there doesn't seem to be an end in sight.

My doctors are stumped. The cardiologist doesn't want to increase or change my medication, and the GP has recommended that I seek second opinions, so that means finding a new endocrinologist and a new cardiologist, at the very least. I'm even considering going to a naturopath - I want to talk to someone who can look at the whole picture and come up with some new ideas, maybe see something that the medical doctors haven't.

So I've given it a lot of thought. I don't really want to step back from anything, but I'm going to have to cut back on some community activities until this gets solved. I don't expect much to change with Austin PyLadies - all our members are so motivated and involved that the group is practically running itself these days. I had planned on being very involved with SciPy when it comes to Austin in June, but I may have to withdraw from that. I have started putting together another beginner Python workshop for some time in July - that will probably go ahead, although I may be looking for some help. And PyTexas in August is probably off the calendar unless my doctors have come up with something helpful by then.

And DjangoCon? Well, we'll see about DjangoCon. I haven't missed one yet.

Powered by Django

About


resume
django people
linkedin
twitter
flickr
readernaut

Blogs I read:
Julia Elman
Die in a Fire
Simon Willison
The Real Katie
Zed Shaw
Girl Developer


Powered by Django

Resume

Barbara Shaurette

LocationAustin, Texas
Emailbarbara.shaurette@gmail.com
Websitehttp://www.mechanicalgirl.com/
LinkedInhttp://www.linkedin.com/in/barbarashaurette/
Otherhttps://people.djangoproject.com/bshaurette/

What I'm interested in:

A position that incorporates application design and development, database design and development, and scripting in a Python-focused environment. I'm looking for the opportunity to do work that involves data analysis and reporting - I have some experience already, and that's the direction I'd like to continue in. I'm also interested in putting my project management skills to work in an engineering leadership role.

What I'm good at:

Why I'm good at it:

Active side projects:
http://www.mechanicalgirl.com/ (Python/Django)
http://www.fivesongsdaily.com/ (Python/Django) (test account available upon request)

Github projects and code samples:
http://github.com/mechanicalgirl
https://github.com/jnoller/PythonSecretSanta
http://resume.github.com/?mechanicalgirl

Conferences and Training:
DjangoCon 2008/2009/2010/2011/2012
PyCon 2009/2010/2012/2013
PDX Python Workshop mentor
PyCon 2013 - Young Coders tutorials, instructor
Austin Women's Python workshops, instructor

Organizations
Python Software Foundation (April 2013 to Present)
Member
Computer Science Teachers Association (September 2012 to Present)
Industry advocate, helping to mentor students and develop primary/high school CS curriculum
PyLadies (November 2012 to Present)
Founder, Austin chapter

Employment History

10/2012 - 04/2013
Texas Tribune
Software Engineer: Python/Django and PostgreSQL/MySQL work on data applications that illustrate the workings of such institutions as the Texas state legislature and prison system for TexasTribune.org.

11/2008 - 09/2012
Live Nation Merchandise
Senior Software Engineer: PHP, Python, Django and MySQL work on high-profile, high-traffic sites for artists such as U2, KISS, and Madonna (including CMS, media processing, reporting tools); API development; database design and management; dev/ops (release management, internal environment administration)

11/2007 - 11/2008
Tippit, Inc.
Senior Software Engineer: Development work on ETL, internal CRM and business intelligence tools, and restructuring of the data warehouse - this work involved Python, Django, PHP, mySQL and other related technologies

07/2007 - 11/2007
Live Nation Merchandise
Senior Software Engineer: Rewrite of the ecommerce site (in XCode/WebObjects), and development/maintenance of artist web sites - this work involved PHP, MySQL, and a significant amount of shell scripting

03/2007 - 06/2007
Live Nation Entertainment
Senior Applications Developer: Development and support on the event search site, Zend Framework upgrade for internationalization and cacheing - this work involved PHP and MySQL, XML/XSLT, and some C++

03/2004 - 03/2007
Adteractive, Inc.
Senior Applications Developer: Platform engineering/data warehousing, ETL, development on our PHP framework, APIs for Java validation service, coordinating the release of new PHP applications
Team Lead/Application Development: Managed developer teams through build/launch/maintenance cycles
Application Developer: Writing data models to evaluate and transfer transaction data - most of this work was in Perl and MySQL

07/2003 - 03/2004
Self-employed
General web development work, contract web design/development for local clients, primarily using HTML, JavaScript and CSS

07/1999 - 07/2003
Vivendi/Universal Inc.
Game Producer/Developer: Writing original game engines for online casual and casino games, primarily in Flash/ActionScript, with some Java work. Developed and supported a network of gaming web sites.
Web Developer: Development and support of Berkeley Systems and Sierra Online gaming sites. Most of this was front-end work - HTML/CSS and JavaScript (with some ColdFusion).

References and Recommendations

References are available upon request. A number of professional recommendations can also be found on my LinkedIn profile: http://www.linkedin.com/in/barbarashaurette

Last updated: September 18, 2012

Powered by Django

Customizing a Django RSS Feed

Date: Mar 09, 2015 | Category: Django 1.3

The Framework: Django 1.3 (not my choice!)

The Mission: Create an RSS feed that includes an extra field for full story content, plus a few additional fields for images

I know. It's 2015 and we're still on 1.3. But the changes to Django syndication since 1.3 haven't been that dramatic, ...

Read More

Powered by Django

PyCon 2014

Date: Apr 27, 2014 | Category: PyCon Python

I just want to pop in here briefly and let everyone know that PyCon 2014 went well! It's a few weeks in the past already, but I've been busy with a lot of follow-up projects ever since I got back.

A few people remarked - and I agree - ...

Read More

Powered by Django

A computer science classroom project without a name

Date: Sep 17, 2013 | Category: CS Education

A little over a month ago now, just as the new school year was about to begin, I had the privilege of attending a meeting of the local chapter of Computer Science Teachers Association here in Austin. I didn't really have any plans - my goal was just ...

Read More

Powered by Django

An open letter to tech conference organizers

Date: May 31, 2013 | Category: Personal

Make that "conference organizers who are interested in increasing diversity among your attendees, or in your community, or (hopefully), both".

Take what I'm about to suggest with a grain of salt. I'm a programmer and a woman who's been going to conferences for several years now. I have a ton ...

Read More

Powered by Django

My weird health issues

Date: May 16, 2013 | Category: Personal

If we're connected on Facebook, you've probably already seen bits and pieces of this story. Is it weird to be talking about my health problems on what is ostensibly a tech blog? Maybe. But there are enough people who have been curious that I thought I'd better explain what's going ...

Read More

Powered by Django