Current Twitter Status

See status in context

Subsidized Fear

Terror Alert Level

Into The Past »

Blog Entries Tagged With “development” (Show All Items Tagged With “development”)

Comments Closed Temporarily While I Do Some Plumbing

Posted on Tuesday, June 24, 2008 @ 11:31 CDT by Daniel Andrlik

I’ve had to shut off commenting functionality for the time being folks. The spammers have been trying hard to get in, and the code that I’ve written to run comments though Akismet for spam checking is occasionally resulting in a spinning process on the server if it gets too many requests. So, I’m rewriting my spam checking code, and will hopefully finish that up and have commenting functions available again soon.

Quick Post: My Pownces, Let Me Show You Them

Posted on Wednesday, March 5, 2008 @ 17:12 CST by Daniel Andrlik

Heh, I had a little fun this afternoon writing a little Django app for my site that will regularly import my public Pownce notes and allow me to display them in the sidebar. It’s really just a modified version of the app I’m using for my Twitter statuses, except that it has some additional logic for handling the different types of Pownce notes.

The thing I’m most happy about is that if I post a public Pownce event, it will display the event with the appropriate microformat markup. Events also include a link to a Google Map of the location, as well as a link to an iCal file for the event. Those last two are provided for free by the Pownce API, so it just seemed to make sense to use them.

Eventually, the look will get redesigned as I redo this site’s design, but for now I’m pleased with it.

Happy Powncing!

Updates, ToDo and a Request for Feedback

Posted on Thursday, December 6, 2007 @ 22:16 CST by Daniel Andrlik

Hopefully not too many people tried to stop by the site today, because I had a pretty severe outage due to my own foolishness. I’ve been trying to implement a few new features to the site, and in one particularly bad move I managed to wipe an important file that isn’t stored in my SCM because it is server dependent. I keep it separate to help simplify testing between different servers and in the general hope that one day I’ll be able to abstract away the code for this site so that it can be packaged up and deployed easily to other people’s servers. Anyway, I had wiped the file and replaced it with a shoddily written copy, and when that failed to work I panicked and wiped everything to redeploy my entire installation.

Not my finest moment, not by a long shot.

Anyway, there are a few new features now, only one of which is actually visible to the user, because when you are coding for yourself, you should always put yourself first in line for awesomeness. I made some improvements to the composing process, and did some caching and database backend work. For the user, I’ve made the link roll omnipresent on the site, because links = love and expanded the purpose of the front page a bit. Previously, I would display a heavily truncated edition of my most recent blog post, and my most recent link. On the new front page, you will have more of a short tumblelog of recent activity. Under the advice of my good friend DHP, I’ve made sure that the most recent blog post remains sticky at the top, with the recent activity in all categories down below.

Honestly, I’m still conflicted on this new look, as I’m also tempted to just display the latest item in each category (blog, links and photos), but that seems not much better than I was doing before. I’d love to get your feedback regarding whether you feel the front page is an improvement, or whether you would prefer a tighter summary of each category and quick access to the footer.

I’m amassing quite a todo list for the site, and for my own benefit as well of those of you who are strangely curious, I will share. Here it is in no particular order:

  • Finalize front page design (of course)
  • Fine tune the caching so that it stays responsive and unobtrusive.
  • Develop style sheet for mobile browsers
  • Refine default style sheet to improve readability
  • Add additional media types for some new projects ;-)
  • Finish XML-RPC interface
  • Improve internal search application
  • Improve Akismet integration (I report spam/ham, but via the command line. Need to add it to admin page)
  • Connect OpenID logins to Django auth system to take advantage of native features

That should keep me busy for a little while, I expect. I’ve also got a number of other posts that have been sitting in the queue as drafts including a few reviews I’ve been procrastinating on, so I’ll be finishing those too. Yay, for new content!

Hopefully, I’ll get all of this done soon, but in the meantime you can stalk me via the interwub. Please consider leaving me some feedback either by posting a comment or by emailing me at daniel at andrlik dot org.

Ahem

Posted on Wednesday, November 14, 2007 @ 10:50 CST by Daniel Andrlik

<clears throat>

This is actually just a short post to warn you that there will be a pretty major overhaul to the site in the near future. The majority of this will consist of a redesign to improve readability, as well as making the site play nicer with mobile browsers, specifically Opera Mobile and WebKit. I may add a few new features as well, such as a few different media types. Right now the site has clear demarcations for browsing the different types of media, although I am considering also enabling a more tumblelog-like experience. Right now, you can get the tumblelog interface in the primary feed for this site, but I’m going to present a way of getting that experience on the site itself.

I also have a few other surprises in the works that I’m not ready to talk about yet, but they should be pretty cool.

Stay tuned.

Fun With Django Feeds

Posted on Friday, August 3, 2007 @ 02:04 CDT by Daniel Andrlik

I would like to take a moment to show you how easy it is to create feeds in Django, and the easiest way to do that is by example. For brevity’s sake, I’m going to use a simplified version of a Django-powered blog. So, let’s say you have a simple blog, where posts consist of a title, slug, pub_date, body and some tags. So your model would look something like this:

blog/models.py

from django.db import models
from tag.fields import TagField
from datetime import datetime

class Entry(models.Model):
    title = models.CharField(maxlength=250)
    slug = models.SlugField(
                 maxlength=250,
                 prepopulate_from=('title'),
                 unique_for_date='pub_date'
    )
    body = models.TextField()
    pub_date = models.DateTimeField(default=datetime.now())
    is_draft = models.BooleanField(default=True)
    allow_comments = models.BooleanField(default=True)
    tags = TagField()
    
    def __unicode__(self):
        return self.title
    
    def get_absolute_url(self):
        #You would fill this in here and call it when you need it or 
        #use the permalink decorator
        #Regardless, you want to customize it for your urls.py
        pass

Now, I’m assuming you already know something about the Django ORM, but I’ll summarize for those of you that don’t. Essentially, we are creating an object of type Entry, which represents a table in your database and has the attributes I listed above. I’ve added a few constraints, such as requiring the slug field to be unique for a given date, since in most cases you will probably build a permalink along the lines of /year/month/day/slug. I’ve also cheated and added two boolean fields which designate if the entry is a draft, and if it allows comments, because they are too useful to leave out, even in an example. TagField is supplied by the django-tagging app, and doesn’t really affect the rest of this example, but I love it so I’m going to leave it in. ;-)

Okay, so you’ve got your model and you have used it to load up some entries, and now it suddenly occurs to you: What’s a blog without a subscription feed? The answer to that question is: Probably not worth the effort to remember visiting on a regular basis. You need an RSS feed! Luckily for you, Django makes this dead simple.

So, the first order of business is to define a feed class to represent your data. Unless you have very complex needs, this is very simple because you just have to subclass the Feed class in Django. You’ll have to define a few variables and then tell the feed what items it should be displaying and what date is the representative pubdate. So, a simple example might look like this:

feeds.py

from django.contrib.syndication.feeds import Feed
from blog.models import Entry

class BlogFeed(Feed):
    '''Feed for latest 15 blog entries'''
    #These could also be pulled from your settings.py file to avoid repetitive hardcoding
    title='My Blog'
    link='http://www.example.com' #URI of site
    description='Latest Blog Entries'
    
    item_author_name='Joe Blow'
    item_author_email='joe@example.com'
    item_author_link='http://www.example.com' #URI of author
    
    def items(self):
        #What items to use in the feed
        return Entry.objects.filter(is_draft=False).order_by('-pub_date')[:15]
    
    def item_pubdate(self,item):
        #For each item, what is the pubdate?
        return item.pub_date

So, that’s a simple feed. Now you need to assign this feed to a url, which you do by adding it to your urls.py file. I’m going to just include the feed urls line rather than including an entire site description.

urls.py

from django.conf.urls.defaults import *
from feeds import *

#Here you add a dictionary of feeds with a slug you want them to correspond to

site_feeds = {
        'blog':BlogFeed
}

urlpatterns = patterns('',
  #Lots of patterns omitted here
  (r'^feeds/(?P&lt;url&gt;.*)/$', 'django.contrib.syndication.views.feed',{'feed_dict':site_feeds}),
)

This tells Django that for every time it encounters a request beginning with feeds, it should take the remainder of the url as a slug and find the corresponding feed class in site_feeds. There is only one step left, making the templates. Don’t worry, this is the easiest part.

Every feed needs two templates, although you can reuse templates by specifying the title_template and description_template in your feed class. Otherwise, Django will look for templates that match your feed’s slug identifier in the templates/feeds directory, where templates is your base directory for templates. In this case it will be looking for blog_title.html and blog_description.html. Both templates get passed one variable: obj, which represents a single item in the feed. Both are ridculously simple:

blog_title.html

{{ obj.title }}

blog_description.html

{{ obj.body }}

They are really that simple. You can, of course, apply all your favorite Django template filters or add extra formatting if you wish. If you want to include any other information that you might pull via template tags, you can use those as well. For example if you wanted to also include a comment count your description template would look like this:

blog_description.html

{% load comments %}
{% get_comment_count for blog.entry obj.id as comment_count %}
{{ obj.body }}
{{ comment_count }} comment{{ comment_count|pluralize }} on this entry.

By default, Django will serve up your feed as RSS 2.0, however, you can also create Atom feeds just as easily. You can even serve up both types of feeds by subclassing your BlogFeed class like so:

feeds.py

from django.contrib.syndication.feeds import Feed
from blog.models import Entry
from django.utils.feedgenerator import Atom1Feed

#For brevity's sake, I'm omitting the BlogFeed I described above.

class AtomBlogFeed(BlogFeed):
    feed_type = Atom1Feed
    subtitle = BlogFeed.description

That’s all there is to it! Simply assign it a feed slug and either create new templates or specify in the AtomBlogFeed class to use the same templates as BlogFeed.

It is possible to completely customize your feeds, but that’s a little out of the scope of this post. This basic approach should work for the majority of cases, and if you need to do something more advanced with your feed, take a moment to browse through the official documentation as there are a wealth of options available to you.

This may initially look like a lot of work, but believe me this takes no time at all. This site generates feeds for every kind of content, including by tag, and tag per category, and I was able to write all of those feeds and have them being served up in about twenty minutes. For a simple example like I am showing here you can be up with feeds in less than ten!

Django makes feed generation quick and easy, and like most aspects of Django, is a joy to work with. Go ahead, take a moment and play with it. If you need an app to work with, you can either flesh out this example or you can go through the official tutorial. Afterwards, I’m pretty sure you’ll be hooked. ;-)

A Short Post On Spam Protection

Posted on Sunday, July 29, 2007 @ 23:30 CDT by Daniel Andrlik

Well, it’s official. I’ve had my first few spammers attempt to leave comments on the new site. Unfortunately for them, their efforts are to no avail.

This is because I use a modified version of the Django comment application that I hacked together myself. By default, all comments that are posted on this site are analyzed by Akismet, which I’m finding remarkably effective at spotting spam. If a comment is found to be spam, it is recorded in the database, where I can recover it later if I have reason to do so. Unlike with other comments, this is done without emailing me and I can blissfully ignore the whole process unless someone complains that their comment was marked with a false positive. In fact, I don’t even have to see them as I can filter out all those comments when browsing the administration section of the site. Maintenance is also not an issue as the application regularly deletes any comments labeled as spam that are more than 30 days old. It works pretty smoothly so far.

I had been waiting for the first spam attack on the post-relaunch version of the site, and I’ve been quite pleased with how well the system I have in place is working. I’m even more pleased with what a joy using a framework like Django is for development, but that’s a subject that deserves its own post.

In addition, the spammers have even provided me with valuable debugging information. A few of their spambots’ attempts to post comments threw errors that I hadn’t anticipated when I was writing the code for this site. The errors were actually quite simple mistakes that frankly I’m a little embarrassed that I didn’t plan for. Luckily, Django emails me a backtrace of any 500 error that occurs, and with that information, I was able to fix those problems in about five minutes. So, I guess sometimes spam is good for something. Thanks, spammers! ;-)

If you are looking for better spam protection on your site, I cannot recommend Akismet enough. It is remarkably effective and has an open API, which allows you to integrate their service with virtually any application. Information on how to get a free API key can be found here.

If you are looking to include Akismet in your Django site, then I’d strongly recommend you check out James Bennett’s comment-utils, which is far more elegant and robust than my implementation. Unfortunately for me, it was released after I had already put together my solution, and for my needs I don’t really have a reason to switch as of yet. However, if you are just starting to get ready to deal with comment moderation in Django, you really can’t go wrong by using comment-utils.

Into The Past »