Tag Archives: wordpress

HOWTO: Share a Nav Bar between Django and WordPress

At Spotivate, we used Django as our backend infrastructure. A few months ago, we wanted to put up a blog and WordPress was the obvious choice due to the amount of tools and plugins available. We also needed some amount of WordPress customization that neither WordPress.com nor Tumblr can provide. Ideally, both Django and WordPress are hosted on the same server and accessible through the same domain name (www.spotivate.com). Not a lot has been written about how Django and WordPress can live happily under one roof. Even less so on how to share UI components between the two. In our case, we wanted to share the main nav bar between the two frameworks, so that users don’t feel that they are leaving the Spotivate experience when they are reading our blog.

Here were the design requirements:

  1. Django and WordPress both running in the same (EC2) instance. Both through Apache HTTP Server. Both using the same MySQL instance.
  2. There is a main nav bar on the Spotivate web site. We wanted this nav bar to be on our blog. The nav bar indicates whether the current user is logged in (and if so, a user thumbnail), the currently selected tab, and various statistics about the logged in user.
  3. URL Namespace
    • /blog goes to WordPress
    • Everything else goes to Django

Here’s what our main nav bar looks like:

Spotivate Main Nav Bar

Spotivate Main Nav Bar

A bit of background. Our Django environment runs under Apache through WSGI. Before WordPress, we had it setup so that all traffic goes to Django (with the exception of static files). Here’s a snippet from our httpd.conf file that enabled this.

<VirtualHost *:80>
ServerName www.spotivate.com
WSGIScriptAlias / "/home/ec2-user/src/spotivate/server/apache/django.wsgi"

<Directory "/home/ec2-user/src/spotivate/server/apache">
Order allow,deny
Allow from all
</Directory>

Alias /static/admin/ "/usr/lib/python2.6/site-packages/django/contrib/admin/static/admin/"
<Directory "/usr/lib/python2.6/site-packages/django/contrib/admin/static/admin/">
Order allow,deny
Allow from all
</Directory>

Alias /static/ "/home/ec2-user/src/spotivate/server/static/"
<Directory "/home/ec2-user/src/spotivate/server/static/">
Order allow,deny
Allow from all
</Directory>

</VirtualHost>

We installed WordPress under our Django “statics” folder, but it can be any folder really. We followed the normal installation procedure of WordPress and installed the database in our current MySQL instance.

Then we changed our httpd.conf by adding the following directives to our existing VirtualHost block:

<VirtualHost *:80>
...
...
# wordpress blog
Alias /blog "/home/ec2-user/server/static/blog"
<Directory "/home/ec2-user/server/static/blog">
Order allow,deny
Allow from all
AllowOverride FileInfo
</Directory>
...
...
</VirtualHost>

Restart the httpd server. Now, we are able to go to http://www.spotivate.com/blog/wp-admin and log in. Next step is to tell WordPress that it belongs under blog by going to Settings >> General. There, change both WordPress Address and Site Address to www.spotivate.com/blog.

Spotivate Blog General Settings

Spotivate Blog General Settings

At this point, we have ourselves a fairly functional stand-alone WordPress blog, showing the default Hello World post under http://www.spotivate.com/blog. Also, all our Django code still works. Great! Now, onto the harder task. Add our nav bar to WordPress by mucking around with header.php and footer.php. We are using Genesis WordPress framework, but this trick should work for most.

The nav bar and any accompanying logic (CSS / Javascript) will be served from Django. Before we had the blog, the nav bar was a piece of HTML in our base template, which also contains reference to CSS file that controls how it looks, and reference to Javascript file that handles hover events, drop down menu, event logging, etc. We want to host all of this code in Django still, since only Django know who the logged in user is. To make nav bar work externally, we need to chop up our base template so that the nav bar can be re-used in WordPress. Then over in WordPress, we will modify header.php and footer.php to call Django to get the nav bar code, and add it to the page dynamically via Javascript.

On Django side, we create two URL mappings:

/blog_head

This will return stuff that will go into thetag of the blog. This will include our CSS and all necessary Javascript (i.e. our Javascript, Google analytics, JQuery, FB, Twitter APIs). Have a look!

/blog_navbar

This will return HTML of the nav bar. No body or html tags. Just the div. Checkout the source to see what I mean, both as an authenticated and un-authenticated user.

Once we got Django to serve the above URLs properly, we can modify header.php by adding this block of code to before </head>. This pretty much adds all our Javascript and CSS code to our blog. This also allows us to reuse CSS definitions in our blog.

...
...
<!-- Django integration: read from /blog_head -->
<?php
$contents = file_get_contents('http://www.spotivate.com/blog_head');
echo $contents;
?>
</head>

Finally, modify footer.php by adding this block of code to before </body>.

...
...
<!-- Django integration: read from /blog_navbar -->
<div id="spotivate-blog-navbar" style="z-index:1000; position: fixed; height: 45px;">
</div>
<script>
$(function() {
$('#spotivate-blog-navbar').load('/blog_navbar');
});
</script>
</body>

The first bit of code defines an empty navbar div with id spotivate-blog-navbar, with fixed positioning and pre-defined height. We wanted the nav bar to float over any blog content just like in our main website. Then there’s a bit of Javascript that loads /blog_navbar (which calls our Django view mentioned above), and stuffs the content into the spotivate-blog-navbar div.

To be honest, it’s not the most pleasing user experience, as the user will see the blog post first, and a split second later, the nav bar shows up.. But it works!

Here’s how our website looks:

Spotivate Website

And here’s how our blog looks:

Spotivate Blog

We spent quite a bit of time making sure the experience feels integrated, and we feel like we have achieved that.

Do you have any other tips and gotchas while integrating Django and WordPress?

HOW TO: Install WordPress on Amazon EC2

First thing’s first. I am kinda new to WordPress. (Yes, I said I am behind in technologies in my previous post, didn’t I?) I setup a WordPress blog for Spotivate a few months ago. Today, I set up my own WordPress on an Amazon EC2 micro instance. Here are the steps I took.

Christophe Coenraets has an amazing tutorial on how to install WordPress on EC2 here. So I am not going to repeat it, since it was really that simple and took less that 5 minutes as advertised.

A few comments:

  • I didn’t create a small instance. Instead, I chose a (Free) micro instance. Why? Well, it’s free. Also, micro will do for now given I have no traffic. Plus, I want to show you how to migrate / upgrade from micro to small later!
  • There are a few typos in the tutorial:
    • mysql_secure_Installation should be mysql_secure_installation
    • tar -xzvf latest.tar.gzcd should be tar -xzvf latest.tar.gz
  • If you followed the instructions given by Christophe, the owner of the blog folder is “root”. Apache runs as “apache” by default. You will have problem uploading plugins and media files later on, since apache != root. Change the owner of /var/www/html/blog to apache:apache by running this command:
    sudo chown -R apache:apache /var/www/html/blog

Now that the URL http://www.jorgechang.com/blog is up, I want to make it so that http://www.jorgechang.com brings the user there as well. There are a few ways I can do that.

  1. Move my blog folder to root as described here. Yes, it looks complicated but not really. Just a matter of moving the blog directory and reconfiguring a few things like Permalinks. I’ve decided against that because I want to keep the URLs of my blog posts under /blog/, e.g. /blog/hello-world. I have other projects in mind, and want freedom over my URL namespace in the future. REMEMBER: Once your blog post is published, you need to make sure that the URL works forever, as other people will likely link to your post if your post is any good. You need to maintain backward compatibility whenever you change your URL structure, so better to keep all blog related activities isolated to /blog.
  2. Setup HTTP redirect so that the end users are redirected to http://www.jorgechang.com/blog.

I am going with redirect method. Now, there are difference kinds of redirect. SEOmoz has an excellent article here that describes HTTP Redirection in detail. Basically, there are three main types of redirect:

  1. 301 (Moved permanently)
  2. 302 (Moved temporarily)
  3. Meta Refresh

Option 3 requires the most work for everyone since I need to write an index.html with meta tag, and the end user’s browser need to do more work (load the page, parse, execute meta refresh, etc) and hence slower.

The difference between 1 and 2 is very subtle, and mainly impacts how search engines crawl and index your pages. 301 is the most suitable option, since I don’t plan on having anything other than my blog on my home page in the foreseeable future.

Edit /etc/httpd/conf/httpd.conf and stick this block of code to the end of the file:

RewriteEngine On
RedirectMatch 301 /index.html /blog

Restart Apache by running this command:

sudo service httpd restart

Now, the URLs for my blog posts look something like /blog?p=1. It doesn’t look very pretty and also affects SEO. Here’s how you can make it look more like /blog/hello-world.

Again, edit /etc/httpd/conf/httpd.conf and look for the following blocks of code and change AllowOverride from None to All. Restart Apache HTTP server afterwards.

<Directory />
Options FollowSymLinks
AllowOverride All
</Directory>
<Directory "/var/www/html">
Options Indexes FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
</Directory>

Create an .htaccess file in your blog folder. If you follow the instructions outlined by Christophe Coenraets, then your blog folder would be /var/www/html/blog. A lot of examples online tell you to create an empty .htaccess file, chmod it with 666 permission, and let WordPress admin handle the changes. I highly recommend against that due to security risk. Most people forget to change it back to 644. Instead, simply create the file and with the following content:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /blog/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /blog/index.php [L]
</IfModule>

Now, go to your WordPress admin. Navigate over to Settings >> Permalinks. Here’s what you should see.

Wordpress Permalink Settings

Pick one that is suitable for you. Yoast suggested that it’s best to stick with “Post name” to give your post a timeless look, so I follow his recommendation. Click Save Changes and voila, your blog post URLs are now readable and timeless.

Next: Themes, plug-ins, custom CSS, nav bar, and more! (Did I say the more I learn, the more behind I feel?)