<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Beardy Geek</title>
	<atom:link href="http://www.beardygeek.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.beardygeek.com</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Fri, 30 Jul 2010 21:48:02 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Django Training in the UK</title>
		<link>http://www.beardygeek.com/2010/07/django-training-in-the-uk/</link>
		<comments>http://www.beardygeek.com/2010/07/django-training-in-the-uk/#comments</comments>
		<pubDate>Fri, 30 Jul 2010 21:48:02 +0000</pubDate>
		<dc:creator>BeardyGeek</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[training]]></category>

		<guid isPermaLink="false">http://www.beardygeek.com/?p=150</guid>
		<description><![CDATA[In Autumn 2010 I will be running several Django courses throughout the UK.  The dates and locations will be based on demand, so please signup here to express your interest, and I&#8217;ll contact you when the venues have been arranged.
There will be 2 different types of courses:

Django template design &#8211; 1 day &#8211; for html/css [...]]]></description>
			<content:encoded><![CDATA[<p>In Autumn 2010 I will be running several Django courses throughout the UK.  The dates and locations will be based on demand, so please <a href="http://www.eventbrite.com/event/784050115?ref=elink" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.eventbrite.com/event/784050115?ref=elink&amp;referer=');">signup here</a> to express your interest, and I&#8217;ll contact you when the venues have been arranged.</p>
<p>There will be 2 different types of courses:</p>
<ul>
<li>Django template design &#8211; 1 day &#8211; for html/css coders who need to be able to fashion a template around the data being passed through by Django</li>
<li>Django introduction for programmers &#8211; 2 days &#8211; for those with web development experience who want to hit the ground running.</li>
</ul>
<p>The cost will be around the £200 per day mark.  I&#8217;ll publish more firm details soon.</p>
<p><a href="http://www.eventbrite.com/event/784050115?ref=ebtn" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.eventbrite.com/event/784050115?ref=ebtn&amp;referer=');"><img src="http://www.eventbrite.com/registerbutton?eid=784050115" border="0" alt="Register for Django Training UK on Eventbrite" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.beardygeek.com/2010/07/django-training-in-the-uk/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>New Django Site &#8211; Blog Twin</title>
		<link>http://www.beardygeek.com/2010/05/new-django-site-blog-twin/</link>
		<comments>http://www.beardygeek.com/2010/05/new-django-site-blog-twin/#comments</comments>
		<pubDate>Tue, 18 May 2010 22:30:08 +0000</pubDate>
		<dc:creator>BeardyGeek</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[site]]></category>

		<guid isPermaLink="false">http://www.beardygeek.com/?p=136</guid>
		<description><![CDATA[I created Blog Twin after reading a blog post by Viper Chill entitled The Secret to growing your blog twice as fast with half the effort, I decided to create a site that would help people find a blogging partner.
Blog Twin is written in Django (naturally!).  You register, add details of your blog, and wait [...]]]></description>
			<content:encoded><![CDATA[<p>I created <a href="http://www.blogtwin.com/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.blogtwin.com/?referer=');">Blog Twin</a> after reading a blog post by Viper Chill entitled <a href="http://www.viperchill.com/fast-blog-growth/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.viperchill.com/fast-blog-growth/?referer=');">The Secret to growing your blog twice as fast with half the effort</a>, I decided to create a site that would help people find a blogging partner.</p>
<p><a href="http://www.blogtwin.com" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.blogtwin.com?referer=');">Blog Twin</a> is written in Django (naturally!).  You register, add details of your blog, and wait for someone else to come along and find you.  Or you can browse through and try and find a site in  a similar niche with similar stats to you.</p>
<p>There&#8217;s also the ability to tag entries, and filter by the tags.</p>
<p>It&#8217;s still a very early beta (I only started doing it 2 days ago), so any feedback, or bug reports, are most welcome.</p>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.beardygeek.com/2010/05/new-django-site-blog-twin/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Using Mind Maps to Create Blog Posts</title>
		<link>http://www.beardygeek.com/2010/05/using-mind-maps-to-create-blog-posts/</link>
		<comments>http://www.beardygeek.com/2010/05/using-mind-maps-to-create-blog-posts/#comments</comments>
		<pubDate>Mon, 17 May 2010 08:30:30 +0000</pubDate>
		<dc:creator>BeardyGeek</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[mind maps]]></category>

		<guid isPermaLink="false">http://www.beardygeek.com/?p=131</guid>
		<description><![CDATA[If you&#8217;ve ever wanted to find an easier, more structured way to plan your blog posts and articles, using mind maps is a great way to go.
Creating blog posts using mind maps
(This links to my new blog, which has a less technical, more business oriented slant.)
]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve ever wanted to find an easier, more structured way to plan your blog posts and articles, using mind maps is a great way to go.</p>
<p><a href="http://www.stuartkmarsh.com/2010/05/creating-blog-posts-using-mind-maps/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.stuartkmarsh.com/2010/05/creating-blog-posts-using-mind-maps/?referer=');">Creating blog posts using mind maps</a></p>
<p>(This links to my new blog, which has a less technical, more business oriented slant.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.beardygeek.com/2010/05/using-mind-maps-to-create-blog-posts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Website Stress testing using JMeter</title>
		<link>http://www.beardygeek.com/2010/03/website-stress-testing-using-jmeter/</link>
		<comments>http://www.beardygeek.com/2010/03/website-stress-testing-using-jmeter/#comments</comments>
		<pubDate>Wed, 31 Mar 2010 13:33:54 +0000</pubDate>
		<dc:creator>BeardyGeek</dc:creator>
				<category><![CDATA[Video]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[jmeter]]></category>
		<category><![CDATA[performance testing]]></category>
		<category><![CDATA[stress testing]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://www.beardygeek.com/?p=125</guid>
		<description><![CDATA[Here&#8217;s my latest screencast, showing you how to stress test your website and web applications using JMeter.
	
	
		
			
			
			
			
			
		
	www.youtube.com/watch?v=8NLeq-QxkSw
]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s my latest screencast, showing you how to stress test your website and web applications using <a href="http://jakarta.apache.org/jmeter" target="_blank" onclick="pageTracker._trackPageview('/outgoing/jakarta.apache.org/jmeter?referer=');">JMeter</a>.</p>
<p>	<!-- Smart Youtube -->
	<span class="youtube">
		<object width="480" height="385">
			<param name="movie" value="http://www.youtube-nocookie.com/v/8NLeq-QxkSw&amp;rel=1&amp;color1=d6d6d6&amp;color2=f0f0f0&amp;border=0&amp;fs=1&amp;hl=en&amp;autoplay=0&amp;showinfo=0&amp;iv_load_policy=3&amp;showsearch=0" />
			<param name="allowFullScreen" value="true" />
			<embed wmode="transparent" 
				src="http://www.youtube-nocookie.com/v/8NLeq-QxkSw&amp;rel=1&amp;color1=d6d6d6&amp;color2=f0f0f0&amp;border=0&amp;fs=1&amp;hl=en&amp;autoplay=0&amp;showinfo=0&amp;iv_load_policy=3&amp;showsearch=0" 
				type="application/x-shockwave-flash" 
				allowfullscreen="true" 
				width="480" 
				height="385">
			</embed>
			<param name="wmode" value="transparent" />
		</object>
	</span><a href="http://www.youtube.com/watch?v=8NLeq-QxkSw" onclick="pageTracker._trackPageview('/outgoing/www.youtube.com/watch?v=8NLeq-QxkSw&amp;referer=');">www.youtube.com/watch?v=8NLeq-QxkSw</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.beardygeek.com/2010/03/website-stress-testing-using-jmeter/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Adding Views to the Django Admin</title>
		<link>http://www.beardygeek.com/2010/03/adding-views-to-the-django-admin/</link>
		<comments>http://www.beardygeek.com/2010/03/adding-views-to-the-django-admin/#comments</comments>
		<pubDate>Fri, 26 Mar 2010 11:01:19 +0000</pubDate>
		<dc:creator>BeardyGeek</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.beardygeek.com/?p=90</guid>
		<description><![CDATA[I recently had to write a view that had to be contained within the Django admin area, on a separate page from the models.  Here's the approach I took.]]></description>
			<content:encoded><![CDATA[<p>I recently had to write a view that exported data to csv.  The view had to be contained within the Django admin area, on a separate page from the rest of the apps and models.  Here is the approach I took.</p>
<h2>The Urls</h2>
<p>There are 2 ways to add urls to the admin: the quick and easy way, or the not so quick and easy way.  In this case, as I was only adding a single url, I went for the quick and easy way.  The other way involves extending the get_urls() method of AdminSite, adding to the existing admin url pattern.  I did this:</p>
<pre><code>
(r'^admin/mypage/$', 'myapp.views.my_admin_view'),
(r'^admin/', include(admin.site.urls)),
</code></pre>
<p>Make sure you add your page before the main admin include.</p>
<h2>The View</h2>
<p>When you write your view make sure you use the staff_member_required decorator.</p>
<pre><code>
from django.contrib.admin.views.decorators import staff_member_required
...
@staff_member_required
def my_admin_view(request):
    # view code
</code></pre>
<p>When rendering your view, also make sure you pass RequestContext to the template:</p>
<pre><code>
return render_to_response('my_template.html',
  context_instance=RequestContext(request))
</code>
</pre>
<h2>The Template</h2>
<p>So that your view looks like it belongs in the admin area, you need to extend the admin base site template:</p>
<pre>
<code>
{% extends 'admin/base_site.html' %}
</code>
</pre>
<p>You&#8217;ll also want to add in i18n support, and the admin media:</p>
<pre>
<code>
{% load i18n adminmedia %}
</code>
</pre>
<p>If you want to add in extra styles you can use {% block extrastyle %}, and you could put javascript in {% block extrahead %}.</p>
<h2>Adding form date widgets</h2>
<p>If you have a form on your page that includes date fields, you might want to have the nice django javascript form widgets.  First you need to add the widgets to your form:</p>
<pre>
<code>
from django.contrib.admin import widgets

class AdminForm(forms.Form):
    start_date = forms.DateField(label="Start date",
         widget=widgets.AdminDateWidget())
</code>
</pre>
<p>Next you need to add in the following to your extrahead block (replace admin-media with whatever you&#8217;ve set your admin media url to):</p>
<pre>
<code>
&lt;script type="text/javascript" src="/admin/jsi18n/"&gt;&lt;/script>
&lt;script type="text/javascript" src="/admin-media/js/core.js"&gt;&lt;/script&gt;
{{ form.media }}
</code>
</pre>
<p>You also need to add the admin forms css in the extrastyles block:<br />
<code></p>
<pre>
{{ block.super }}
&lt;link rel="stylesheet" type="text/css" href="/admin-media/css/forms.css" /&gt;
</pre>
<p></code></p>
<h2>Breadcrumbs</h2>
<p>If you want to have the breadcrumb trail at the top of the page, you need to create your own breadcrumb:</p>
<pre>
<code>
{% block breadcrumbs %}&lt;div class="breadcrumbs"&gt;&lt;a href="/admin/"&gt;
{% trans "Home" %}&lt;/a&gt; &gt; My View&lt;/div&gt;{% endblock %}
</code>
</pre>
<h2>Adding a link to the admin index</h2>
<p>When I add a link in, I like it to go in one of the right column boxes, so I usually create a new one and put it above the recent actions box.  To do this, you need to override the admin index.html file.</p>
<p>Create a directory in your templates directory called admin.  Then copy the index.html file from django/contrib/admin/templates to your new directory.</p>
<p>You&#8217;ll see a block called &#8217;sidebar&#8217;.  Under the &#8216;content-related&#8217; div, place the following:</p>
<pre>
<code>
&lt;div class="module"&gt;
  &lt;h2&gt;Admin tools&lt;/h2&gt;
    &lt;ul class="actionlist"&gt;
      &lt;li class="changelink"&gt;
        &lt;a href="/admin/mypage/"&gt;My View&lt;/a&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
&lt;/div&gt;
</code>
</pre>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.beardygeek.com/2010/03/adding-views-to-the-django-admin/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>New Django Site &#8211; The Great British Sleep Survey</title>
		<link>http://www.beardygeek.com/2010/03/new-django-site-the-great-british-sleep-survey/</link>
		<comments>http://www.beardygeek.com/2010/03/new-django-site-the-great-british-sleep-survey/#comments</comments>
		<pubDate>Wed, 24 Mar 2010 20:05:29 +0000</pubDate>
		<dc:creator>BeardyGeek</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Featured]]></category>

		<guid isPermaLink="false">http://www.beardygeek.com/?p=84</guid>
		<description><![CDATA[I've very recently finished a django based site for a company called Sleepio﻿. ]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve very recently finished a django based site for a company called <a title="Sleepio" href="http://www.sleepio.com" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.sleepio.com?referer=');">Sleepio</a>﻿.  The project was to create a survey site, called the Great British Sleep Survey. Once completed, it calculates your sleep score and creates a report tailored to your issues (or lack of).</p>
<p>Also working on the site, doing all the xhtml and css magic was Rui Zhang from <a href="http://borderleft.com/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/borderleft.com/?referer=');">borderleft</a>. If you ever need anyone to turn your designs into an actual web site, he&#8217;s your man. Thanks Rui.</p>
<p>One of the co-founders of Sleepio is Professor Colin Espie, who runs the sleep centre at Glasgow University.  The site is also a collaboration with <a href="http://www.webmd.boots.com/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.webmd.boots.com/?referer=');">Boots Web MD</a>, which offers health and medical advice.</p>
<p>So check it out, complete the survey (you get a free sleep report!), and any feedback is always welcome.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.beardygeek.com/2010/03/new-django-site-the-great-british-sleep-survey/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google Calls for Link Spam Reports</title>
		<link>http://www.beardygeek.com/2010/03/google-calls-for-link-spam-reports/</link>
		<comments>http://www.beardygeek.com/2010/03/google-calls-for-link-spam-reports/#comments</comments>
		<pubDate>Thu, 04 Mar 2010 10:34:45 +0000</pubDate>
		<dc:creator>BeardyGeek</dc:creator>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[google]]></category>

		<guid isPermaLink="false">http://www.beardygeek.com/?p=73</guid>
		<description><![CDATA[In Matt Cutts latest blog post, he calls for users to report any sites they deem 'spammy'.]]></description>
			<content:encoded><![CDATA[<p><img class="size-medium wp-image-75 alignnone" style="border: 0pt none; margin-left: 5px; margin-right: 10px;" title="Spam" src="http://www.beardygeek.com/wp-content/uploads/2010/03/spam1-300x171.jpg" alt="Spam" width="300" height="171" /></p>
<p><a href="http://www.flickr.com/photos/63056612@N00/155554663/" target="_blank" style="font-size: smaller" onclick="pageTracker._trackPageview('/outgoing/www.flickr.com/photos/63056612_N00/155554663/?referer=');">[<em>image attribution</em>]</a></p>
<p>In <a href="http://www.mattcutts.com/blog/calling-for-link-spam-reports/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.mattcutts.com/blog/calling-for-link-spam-reports/?referer=');">Matt Cutts latest blog post</a>, he calls for users to report any sites they deem &#8217;spammy&#8217;.  On the <a href="https://www.google.com/webmasters/tools/spamreport" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.google.com/webmasters/tools/spamreport?referer=');">report form</a>, this includes anything that is considered:</p>
<ul>
<li>Hidden text or links</li>
<li>Misleading or repeated words</li>
<li><label for="description">Page does not match Google&#8217;s description</label></li>
<li><label for="cloaked">Cloaked page</label></li>
<li><label for="redirects">Deceptive redirects</label></li>
<li><label for="doorway">Doorway pages</label></li>
<li><label for="duplicate">Duplicate site or pages</label></li>
</ul>
<p>Matt says that Google have been working on new algorithms to detect link spam, and it seems that through this manual reporting process, Google users will be helping to &#8216;train&#8217; the system to be more effective.</p>
<p>It doesn&#8217;t say yet what action will be taken upon finding such a page, and whether Google will allow webmasters to make amends or defend themselves.  So look out for tales of woe from people removed from Google&#8217;s index for spurious reasons.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.beardygeek.com/2010/03/google-calls-for-link-spam-reports/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django Tips &#8211; Unique Date Querysets</title>
		<link>http://www.beardygeek.com/2009/02/django-tips-unique-date-querysets/</link>
		<comments>http://www.beardygeek.com/2009/02/django-tips-unique-date-querysets/#comments</comments>
		<pubDate>Sun, 15 Feb 2009 18:50:26 +0000</pubDate>
		<dc:creator>BeardyGeek</dc:creator>
				<category><![CDATA[Django]]></category>

		<guid isPermaLink="false">http://www.beardygeek.com/?p=35</guid>
		<description><![CDATA[I swear this particular feature of querysets was made especially for the archive listing of a blog.  You know, the month and year listing in the side bar for all your previous posts. This solves that problem exactly.]]></description>
			<content:encoded><![CDATA[<p>I swear this particular feature of querysets was made especially for the archive listing of a blog.  You know, the month and year listing in the side bar for all your previous posts. This solves that problem exactly.</p>
<p>Let&#8217;s say you have a BlogPost model, and a post_date field within said model.  You want a list on the sidebar of all the unique month and year combinations.  Here&#8217;s what you do:</p>
<p><pre>
<code>
queryset = BlogPost.objects.dates('post_date', 'month')
</code>
</pre>
</p>
<p>And that&#8217;s it.  You&#8217;ll now have a query set full of datetime objects with all your unique months and years.</p>
<p>To get unique years only, substitute &#8216;year&#8217; for &#8216;month&#8217;, and for unique day, month and year, substitute &#8216;day&#8217; for &#8216;month&#8217;.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.beardygeek.com/2009/02/django-tips-unique-date-querysets/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>From Wordpress to Django &#8211; Part 2</title>
		<link>http://www.beardygeek.com/2009/01/from-wordpress-to-django-part-two/</link>
		<comments>http://www.beardygeek.com/2009/01/from-wordpress-to-django-part-two/#comments</comments>
		<pubDate>Tue, 27 Jan 2009 18:59:08 +0000</pubDate>
		<dc:creator>BeardyGeek</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Blogging]]></category>

		<guid isPermaLink="false">http://www.beardygeek.com/?p=46</guid>
		<description><![CDATA[Welcome back.  In part 2 I'll be getting to the meat of the issue, which is retrieving the data from an existing Wordpress blog, and feeding the data into my own models.]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.foundrylabs.co.uk/blog/2009/1/from-wordpress-to-django-part-one/" onclick="pageTracker._trackPageview('/outgoing/www.foundrylabs.co.uk/blog/2009/1/from-wordpress-to-django-part-one/?referer=');">View Part 1</a><br />
<a href="http://github.com/beardygeek/beardygeek-website" onclick="pageTracker._trackPageview('/outgoing/github.com/beardygeek/beardygeek-website?referer=');">Beardy Geek Git Hub Repository</a></p>
<p>Welcome back.  In part 2 I&#8217;ll be getting to the meat of the issue, which is retrieving the data from an existing Wordpress blog, and feeding the data into my own models.</p>
<p>
<h4>Models</h4>
<p>I&#8217;ve decided to start the models from scratch, rather than trying to copy the way Wordpress has laid them out. It should keep things simpler that way.  I&#8217;ll be using the contrib comments system for the post comments, and I&#8217;ll also be creating 3 other models, Category, Tag, and Post. Here&#8217;s the code for the models:</p>
<pre><code>
from django.db import models
from django.contrib.auth.models import User
from datetime import datetime

POST_STATUS = (
               ('P', 'Published'),
               ('U', 'Unpublished'),
)

class Tag(models.Model):
    text = models.CharField(max_length=75)
    slug = models.CharField(max_length=75)

    def __unicode__(self):
        return self.text

class Category(models.Model):
    text = models.CharField(max_length=75)
    slug = models.CharField(max_length=75)

    def __unicode__(self):
        return self.text

    class Meta:
        verbose_name_plural = "categories"

class Post(models.Model):
    title = models.CharField(max_length=75)
    slug = models.CharField(max_length=75)
    content = models.TextField()
    author = models.ForeignKey(User)
    post_date = models.DateTimeField(default=datetime.now)
    status = models.CharField(max_length=1, choices=POST_STATUS)
    categories = models.ManyToManyField(Category)
    tags = models.ManyToManyField(Tag)

    def __unicode__(self):
        return self.title
</code></pre>
</p>
<p>
<h4>Wordpress Export</h4>
<p>Just a quick note: I am using Wordpress Version 2.6.1. Things may be different in other versions, but the code here works on this version. I&#8217;ll go through the code so you should see where the problem is if it doesn&#8217;t work with your version.</p>
<p>OK, if you didn&#8217;t already know, you can export all your Wordpress data into an xml file. Go to your dashboard, click &#8216;Manage&#8217;, and then &#8216;Export&#8217;. Select which authors to restrict (if any) and hit the download button. You should now have the data in an xml file.</p>
<p>
<h4>XML File Editing</h4>
<p>When I first tried to parse this file, I got an error as one of the namespaces used in the document is undeclared. To rectify this, you need to open up the file in a text editor (not an xml editor, you may get the same parse error). Near the top of the file, you should see something like this:</p>
<pre><code>
&lt;rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:wp="http://wordpress.org/export/1.0/"
&gt;
</code></pre>
<p>The missing namespace is &#8216;excerpt&#8217;, and we need to add this. It doesn&#8217;t matter what value you give it. I did this:</p>
<pre><code>
&lt;rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:wp="http://wordpress.org/export/1.0/"
	xmlns:excerpt="mysite"
&gt;
</code></pre>
<p>Save the file and we&#8217;re ready to start parsing the data.</p>
<p>
<h4>XML Parsing</h4>
<p>To parse the XML I have used ElementTree. This is included in Python 2.5, but if you&#8217;re using an earlier version, you can get ElementTree from <a href="http://effbot.org" onclick="pageTracker._trackPageview('/outgoing/effbot.org?referer=');">Effbot.org</a>.</p>
<p>I won&#8217;t include all the code here, just some snippets as examples. To view the full source, please check out the <a href="http://github.com/beardygeek/beardygeek-website" onclick="pageTracker._trackPageview('/outgoing/github.com/beardygeek/beardygeek-website?referer=');">BeardyGeek Github Repository</a>.</p>
<p>First we need to load our xml file.</p>
<pre><code>
tree = ElementTree.parse('c:/wordpress.xml')
</code></pre>
<p>Then find the top level under which our data resides, which is the &#8216;channel&#8217; tag.</p>
<pre><code>
chan = tree.find('channel')
</code></pre>
<p>Now I want to create some shortcut variables for the namespaces that we will use when finding tags.</p>
<pre>
<code>
wp_ns = '{http://wordpress.org/export/1.0/}'
content_ns = '{http://purl.org/rss/1.0/modules/content/}'
</code>
</pre>
<p>Now we can get all the category, tag and item(post) entries:</p>
<pre><code>
cats = chan.findall('{http://wordpress.org/export/1.0/}category')
tags = chan.findall('{http://wordpress.org/export/1.0/}tag')
items = chan.findall('item')
</code></pre>
<p>This will give us lists of all the elements for those three items.</p>
<p>
<h4>Finding and Saving Data</h4>
<p>I&#8217;ll give an example of saving the data using the category tag.</p>
<pre>
<code>
for cat in cats:
        c = Category(text=cat.find(wp_ns + 'cat_name').text,
                 slug=cat.find(wp_ns + 'category_nicename').text)
        c.save()
</code>
</pre>
<p>The tag data is the same as the above.</p>
<p>The item data is a bit more complex. If you look at the xml you&#8217;ve exported, you&#8217;ll see that the item data includes both posts and pages. But it also gives all previous revisions of each post, which will include any drafts saved whilst writing a post. So we need to find all those with a status of &#8216;publish&#8217; and a page type of &#8216;post&#8217;. We&#8217;ll deal with the &#8216;page&#8217; data another time, using Flatpages.</p>
<pre>
<code>
if item.find(wp_ns + 'status').text == 'publish' and
               item.find(wp_ns + 'post_type').text == 'post':
            i = Post(title=item.find('title').text,
                     slug=item.find(wp_ns + 'post_name').text,
                     content=item.find(content_ns + 'encoded').text, author=u,
                     post_date=item.find(wp_ns + 'post_date').text,
                     status='P')
            i.save()
</code>
</pre>
<p>The &#8216;u&#8217; (value for author) is a User object I create earlier in the code that I&#8217;ve used as the default author of each post (see source).</p>
<p>
<h4>Post Categories</h4>
<p>Now we have to find out which categories and tags this post has. Within each &#8216;item&#8217; we have &#8216;category&#8217; data. A bit confusingly this &#8216;category&#8217; data also includes the tags, and to discover that you need to look at the &#8216;domain&#8217; attribute to see which it is. Plus we only need the category with the &#8216;nicename&#8217; in it (slugified).</p>
<pre>
<code>
post_cats = item.findall('category')

for pc in post_cats:
     #check for attributes
     if pc.get('nicename'):
         if pc.attrib['domain'] == 'category':
              c2 = Category.objects.get(slug=pc.attrib['nicename'])
              i.categories.add(c2)
         elif pc.attrib['domain'] == 'tag':
              t2 = Tag.objects.get(slug=pc.attrib['nicename'])
              i.tags.add(t2)
</code>
</pre>
</p>
<p>
<h4>Comments</h4>
<p>The last section deals with comments. I am using the django.contrib.comments module for this.</p>
<pre>
<code><br />
comments = item.findall(wp_ns + 'comment')</p>
<p>for comm in comments:<br />
    if not comm.find(wp_ns + 'comment_author_email').text:<br />
        comm_email = ''<br />
    else:<br />
        comm_email = comm.find(wp_ns + 'comment_author_email').text</p>
<p>        if not comm.find(wp_ns + 'comment_author_url').text:<br />
            comm_url = ''<br />
        else:<br />
            comm_url = comm.find(wp_ns + 'comment_author_url').text</p>
<p>        db_comm = Comment(comment=comm.find(wp_ns + 'comment_content').text,<br />
            ip_address=comm.find(wp_ns + 'comment_author_IP').text,<br />
            object_pk=i.id, submit_date=comm.find(wp_ns + 'comment_date').text,<br />
            user_email=comm_email,<br />
            user_name=comm.find(wp_ns + 'comment_author').text[:50],<br />
            user_url=comm_url,<br />
            content_type=ct, site=site)<br />
        db_comm.save()<br />
</code>
</pre<br />
</p>
<p>
<h4>Conclusion</h4>
<p>Well that wraps it up for this post. I'll cover extracting the data for Flatpages in the next post, but this should give you enough to get started. You can see how to extract the required data from the xml document, so if you want to extend the models beyond what I have, you shouldn't have any problems.  Again, check out the fully code, plus the other file changes (url.py etc) at <a href="http://github.com/beardygeek/beardygeek-website" onclick="pageTracker._trackPageview('/outgoing/github.com/beardygeek/beardygeek-website?referer=');">the Beardy Geek Git Hub Repository</a>. Have fun.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.beardygeek.com/2009/01/from-wordpress-to-django-part-two/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>From Wordpress to Django &#8211; Part 1</title>
		<link>http://www.beardygeek.com/2009/01/from-wordpress-to-django-part-one/</link>
		<comments>http://www.beardygeek.com/2009/01/from-wordpress-to-django-part-one/#comments</comments>
		<pubDate>Wed, 14 Jan 2009 18:55:00 +0000</pubDate>
		<dc:creator>BeardyGeek</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Blogging]]></category>

		<guid isPermaLink="false">http://www.beardygeek.com/?p=43</guid>
		<description><![CDATA[Now don't get me wrong, there's nothing wrong with Wordpress.  It's just that I like to play with stuff, so I thought it would be fun to create a blog in Django, copy all my Wordpress posts across, and add at least some of the functionality that Wordpress has built in.]]></description>
			<content:encoded><![CDATA[<p>Now don&#8217;t get me wrong, there&#8217;s nothing wrong with Wordpress.  It&#8217;s just that I like to play with stuff, so I thought it would be fun to create a blog in Django, copy all my Wordpress posts across, and add at least some of the functionality that Wordpress has built in.</p>
<h4>Open Source</h4>
<p>Throughout this process, so that you can follow along, I will be storing the code in a GitHub repository.  <a href="http://github.com/beardygeek/beardygeek-website" target="_blank" onclick="pageTracker._trackPageview('/outgoing/github.com/beardygeek/beardygeek-website?referer=');">Click here to view the BeardyGeek repository</a></p>
<h4>A Few Considerations</h4>
<p>There are a few things to think about before getting started:</p>
<ol>
<li>Data Conversion &#8211; getting the data from Wordpress into my Django models.  Do I want to keep the same database structure as Wordpress, or create my own?  If I create my own, how will I get the data across?</li>
<li>Services &#8211; how much do I try and implement?  The main ones are comments, tags, pings, anti-spam.</li>
</ol>
<p>I&#8217;m sure more will come to mind as I go through this</p>
<h4>Conclusion</h4>
<p>Well, I&#8217;d better stop jabbering and get on with it then!  Keep an eye on the blog, or watch the Git repo for updates.  I&#8217;ll get done whatever my current workload allows.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.beardygeek.com/2009/01/from-wordpress-to-django-part-one/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
