Archive for January, 2009

Bigger Chicken in Rotisserie

posted on January 28th, 2009 by PyromanX in Greg's Pictures on Flickr

PyromanX posted a photo:

Bigger Chicken in Rotisserie

Almost too big for this thing. At least it came pre-seasoned and I didn’t have to mess with that before cooking. Not enough time for that after work.

Bigger Chicken in Rotisserie

posted on January 28th, 2009 by PyromanX in Greg's Pictures on Flickr

PyromanX posted a photo:

Bigger Chicken in Rotisserie

Almost too big for this thing. At least it came pre-seasoned and I didn’t have to mess with that before cooking. Not enough time for that after work.

A URL Shortening Service for UCF

posted on January 27th, 2009 by Greg in CDWS Projects

The idea for this site came when some co-workers and I were collecting our W2’s and found letters attached with some HR information. One of them had a ridiculously long URL at the bottom of it (…Enroll%20in%20UCF%20Retirement%20Plans…). Before seeing that URL I hadn’t thought of the convenience of services like TinyURL outside of the internet. We realized it would be simple enough to write one that is specific to UCF.

We decided on a few simple features and jumped into pair programming the site with django.  Since Jason was new to Django, he obvserved while I drove. It took less than the rest of the day to finish the site.

Features

Only allows domains that we specify

We created a custom Form Field to accomplish this and made it able to accept a tuple of allowed domains. If anyone needs this on their site they can use the following code.

from django import forms
 
class URLDomainField(forms.URLField):
    domain = ''
 
    def __init__(self, *args, **kwargs):
        # set domain to passed value or default
        self.domain = kwargs.get('domain', ('gregallard.com', 'isthemarketdown.com', 'codespatter.com'))
 
        # remove from list if exists
        try:
            del kwargs['domain']
        except:
            pass
 
        # call parent init
        super(URLDomainField, self).__init__(*args, **kwargs)
 
    def clean(self, value):
        # call parent clean
        value = super(URLDomainField, self).clean(value)
 
        from urlparse import urlparse
        o = urlparse(value)
 
        # endswith accepts tuples and will try them all and will return false if none match
        if not o.hostname.endswith(self.domain):
            raise forms.ValidationError('%s is not a valid url! %s domains only.' % (value, self.domain))
 
        return value

The code to use this would look like this:

class LinkForm(forms.Form):
    url   = URLDomainField(domain=('ivylees.com', 'ucf.edu'))

Automatically creates 5 character alphanumeric string

This method in the model creates a string and makes sure it isn’t in use yet:

    def make_short(self):
        from random import Random
        import string
        cool = False
        while not cool:
            self.short = ''.join( Random().sample(string.letters+string.digits, 5) )
            try:
                r = Link.objects.get(short=self.short)
            except Link.DoesNotExist:
                if self.short != "admin" and self.short != "thank":
                    cool = True

Allows for custom strings

By default it will create a 5 character alphanumeric string to go at the end of the URL, however we added a form field to allow users to specify their own string so that the URL might have more meaning. To strip non alphanumeric characters, we created a simple clean method in the model:

    def clean_short(self):
        import re
        # ^ as first character inside [] negates the set
        # find everything that isn't alphanumeric or a -
        self.short = re.sub('[^\w|\-]', '_', self.short)

Won’t create more short links

If a URL has been submitted before, the site will not create an extra URL for it, instead it will return the existing one to the user. To do this, we added some functionality to the save method:

    def save(self, **kwargs):
        link = Link.objects.filter(url=self.url)[:1]
 
        # if one exists, return it, otherwise save it
        if link:
            # there should be a better way to do this
            # but self = link doesn't work
            self.url   = link[0].url
            self.short = link[0].short
            self.created = link[0].created
            self.id = link[0].id
        else:
            if self.short == '':
                self.make_short()
            else:
                self.clean_short()
            super(Link, self).save(**kwargs)

Just a Prototype

We just wanted to create something simple as a prototype so that hopefully some of the higher-ups will like the idea and we can put it into production.

Pair Programming

This was the first time I had any experience with pair programming and I definitely think it’s a great idea. Jason learned a lot about django, caught my mistakes, and pointed out other things. I solidified my knowledge by showing him what I knew and we both learned some valuable things. For example: using print foo will be displayed in the command window when you are using the django development server. I foresee more pair programming in my future.

Update 2009-01-28

Tim recommended that I remove the chance of profanity to be automatically generated for the url and suggested removing all vowels so that no words will be there. This is the line I added to achieve that.

letters = re.sub('a|e|i|o|u|A|E|I|O|U', '', string.letters)

Pork Loin

posted on January 25th, 2009 by PyromanX in Greg's Pictures on Flickr

PyromanX posted a photo:

Pork Loin

In the rotisserie

Pork Loin

posted on January 25th, 2009 by PyromanX in Greg's Pictures on Flickr

PyromanX posted a photo:

Pork Loin

In the rotisserie

How to Write Django Template Tags

posted on January 22nd, 2009 by Greg Allard in Greg's Posts on Code Spatter

Template tags can be useful for making your applications more reusable by other projects. For this example I will be adding to the
books project that I started in a previous post. Also, I’ve bundled the
example files into a google code project.

Start off by creating a folder called templatetags in your app directory and create two files in it. The first one named __init__.py and the second book_tags.py. There’s 3 things that we need to accomplish with our template tags. The first is to create a tag that will output the url for the action of the form. For example, {% get_book_form_url foo_object %}Next we need to get the form and assign it to a template variable that can be specified by the template variable. For example, {% book_form as bar_var %}. And the third template tag will get the books for an object and place in a template variable. For example, {% books_for_object foo_object as bar_var %}.

from django.template import Library, Node, TemplateSyntaxError
from django.template import Variable, resolve_variable
from django.utils.translation import ugettext as _
from django.contrib.contenttypes.models import ContentType
from django.core.urlresolvers import reverse
from books.models import Book
 
register = Library()
 
def get_contenttype_kwargs(content_object):
    """
    Gets the basic kwargs necessary for form submission url
    """
    kwargs = {'content_type_id':
        ContentType.objects.get_for_model(content_object).id,
    'object_id':
        getattr(content_object, 'pk',
            getattr(content_object, 'id')),
    }
    return kwargs
 
def get_book_form_url(content_object):
    """
    prints url for form action
    """
    kwargs = get_contenttype_kwargs(content_object)
    return reverse('new_book', kwargs=kwargs)
 
class BooksForObjectsNode(Node):
    """
    Get the books and add to the context
    """
    def __init__(self, obj, context_var):
        self.obj = Variable(obj)
        self.context_var = context_var
 
    def render(self, context):
        content_type = ContentType.objects.get_for_model(
            self.obj.resolve(context))
        # create the template var by adding to context
        context[self.context_var] = \
            Book.objects.filter( # find all books for object
                content_type__pk = content_type.id,
                object_id = self.obj.resolve(context).id
            )
        return ''
 
def books_for_object(parser, token):
    """
    Retrieves a list of books for given object
    {% books_for_object foo_object as book_list %}
    """
    try:
        bits = token.split_contents()
    except ValueError:
        raise TemplateSyntaxError(
            _('tag requires exactly two arguments')
    if len(bits) != 4:
        raise TemplateSyntaxError(
            _('tag requires exactly three arguments')
    if bits[2] != 'as':
        raise TemplateSyntaxError(
            _("second argument to tag must be 'as'")
    return BooksForObjectsNode(bits[1], bits[3])
 
def book_form(parser, token):
    """
    Adds a form to the context as given variable
    {% book_form as form %}
    """
    # take steps to ensure template var was formatted properly
    try:
        bits = token.split_contents()
    except ValueError:
        raise TemplateSyntaxError(
            _('tag requires exactly two arguments')
    if bits[1] != 'as':
        raise TemplateSyntaxError(
            _("second argument to tag must be 'as'")
    if len(bits) != 3:
        raise TemplateSyntaxError(
            _('tag requires exactly two arguments')
    # get the form
    return BookFormNode(bits[2])
 
class BookFormNode(Node):
    """
    Get the form and add it to the context
    """
    def __init__(self, context_name):
        self.context_name = context_name
    def render(self, context):
        from books.forms import NewBookForm
        form = NewBookForm()
        # create the template var by adding to context
        context[self.context_name] = form
        return ''
 
# register these tags for use in template files
register.tag('books_for_object', books_for_object)
register.tag('book_form', book_form)
register.simple_tag(get_book_form_url)

Add this to your template

To start adding books to an object, add this code to your template and change my_awesome_object_here to the template variable name of your object.

<h2>Books</h2>
{% load book_tags %}
 
{% books_for_object my_awesome_object_here as books %}
{% for book in books %}
 
<a href="{{ book.get_absolute_url }}">{{ book }}</a> -
        {{ book.description }}
 
{% endfor %}
<h2>Add a book</h2>
<form action="{% get_book_form_url my_awesome_object_here %}" method="post">
{% book_form as form %}
{{ form }}
<input type="submit" value="Go" />
</form>

You can get the template tags source code and the code from
the previous post at the
google code project page or by doing

svn co http://django-books.googlecode.com/svn/trunk books

in a directory on the python path.

Related posts:

  1. How to Write Reusable Apps for Pinax and Django Pinax is a collection of reusable django apps that…
  2. Django RequestContext Example Browsing other peoples’ code is a great way to learn…
  3. Quick Thumbnails in Django I normally like to write code myself instead of installing…

How I Made isthemarketdown.com

posted on January 21st, 2009 by Greg in Personal Projects

The idea came on inauguration day when someone was wondering how the stock market was doing. I had been to http://isobamapresident.com/ earlier in the day and the single serving site idea for the stock market came to mind.

It only took about 3 hours to create after I had the idea.

First 30 minutes: Find free data. Is there a feed or API?
Next 30: I couldn’t find anything useful so I decided to scrape a website using BeautifulSoup.
Next 60: I set up a Django project to put it all together. Created a model to hold the scraped data so I wouldn’t do it every page load. Created a simple view and layed out a template file and simple stylesheet.
Next 15: I found out how to add a method to manage.py so that I could call the scraping from the command line. python manage.py market_parse
Next 15: Debugging and adjusting. I hadn’t looked at the site yet, but there weren’t that many bugs.
Last 30 minutes: add crontab for every 20 minutes on weekdays from 9-5. It took a while to get going because I needed the full python path in the crontab.

So, is the market down?

Diploma Frame

posted on January 18th, 2009 by PyromanX in Greg's Pictures on Flickr

PyromanX posted a photo:

Diploma Frame

After spending over 6 years getting the thing, I might as well put it in a nice frame.

Diploma Frame

posted on January 18th, 2009 by PyromanX in Greg's Pictures on Flickr

PyromanX posted a photo:

Diploma Frame

After spending over 6 years getting the thing, I might as well put it in a nice frame.

Antares

posted on January 18th, 2009 by PyromanX in Greg's Pictures on Flickr

PyromanX posted a photo:

Antares

Named after

Named after the Red Supergiant because the case is huge and has red lights.

Named after the Red Supergiant because the case is huge and has red lights.