<?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>Code Spatter &#187; Server Administration</title>
	<atom:link href="http://codespatter.com/category/server-administration/feed/" rel="self" type="application/rss+xml" />
	<link>http://codespatter.com</link>
	<description></description>
	<lastBuildDate>Fri, 04 Sep 2009 14:59:15 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>How to Display Realtime Traffic Analytics</title>
		<link>http://codespatter.com/2009/09/02/how-to-display-realtime-traffic-analytics/</link>
		<comments>http://codespatter.com/2009/09/02/how-to-display-realtime-traffic-analytics/#comments</comments>
		<pubDate>Wed, 02 Sep 2009 11:26:29 +0000</pubDate>
		<dc:creator>Greg Allard</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Server Administration]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[Caching]]></category>
		<category><![CDATA[Cron]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://codespatter.com/?p=496</guid>
		<description><![CDATA[
	<script type="text/javascript">
	// <![CDATA[
		(function() {
			var links = document.getElementsByTagName('a');
			var query = '&';
			for(var i = 0; i < links.length; i++) {
				if(links[i].href.indexOf('#disqus_thread') >= 0) {
					links[i].innerHTML = 'View Comments';
					query += 'wpid' + i + '=' + encodeURIComponent(links[i].getAttribute('wpid')) + '&';
				}
			}
			document.write('<script charset="utf-8" type="text/javascript" src="http://disqus.com/forums/codespatter/get_num_replies_from_wpid.js?v=2.0' + query + '"><' + '/script>');
		})();
	//]]>
	</script>

	Users of 
Presskit&#8217;n have been asking for traffic statistics on their press releases so I decided I would get them the most recent data possible. At first I was parsing the access log once a minute and when I was testing that I decided it wasn&#8217;t updating fast enough. I&#8217;ve gotten used to everything being [...]


Related posts:<ol><li><a href='http://codespatter.com/2009/04/23/how-to-speed-up-your-django-sites/' rel='bookmark' title='Permanent Link: How to Speed up Your Django Sites with NginX, Memcached, and django-compress'>How to Speed up Your Django Sites with NginX, Memcached, and django-compress</a> <small>A lot of these steps will speed up any kind...</small></li><li><a href='http://codespatter.com/2009/07/08/python-projects-in-users-home-directories-with-wsgi/' rel='bookmark' title='Permanent Link: Python Projects in Users&#8217; Home Directories with wsgi'>Python Projects in Users&#8217; Home Directories with wsgi</a> <small>Letting users put static files and php files in a...</small></li><li><a href='http://codespatter.com/2009/01/15/how-to-write-reusable-apps-for-pinax-and-django/' rel='bookmark' title='Permanent Link: How to Write Reusable Apps for Pinax and Django'>How to Write Reusable Apps for Pinax and Django</a> <small> Pinax is a collection of reusable django apps that...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<div id="attachment_523" class="wp-caption alignright" style="width: 310px">
<a  href="http://presskitn.com" onclick="javascript:pageTracker._trackPageview('/external/presskitn.com');" ><img class="size-medium wp-image-523" title="Presskit'n Hits" src="http://codespatter.com/wp-content/uploads/2009/09/presskitn_hits-300x206.jpg" alt="Presskit'n Hits" width="300" height="206" /></a><p class="wp-caption-text">Presskit&#39;n Hits</p></div>
<p>Users of 
<a  href="http://presskitn.com" onclick="javascript:pageTracker._trackPageview('/external/presskitn.com');" >Presskit&#8217;n</a> have been asking for traffic statistics on their press releases so I decided I would get them the most recent data possible. At first I was parsing the access log once a minute and when I was testing that I decided it wasn&#8217;t updating fast enough. I&#8217;ve gotten used to everything being instant on the internet and I didn&#8217;t want to wait a minute to see how many more views there were. In this post I show how I got it to update on page load using Apache, python, Django, and memcached.</p>
<h3>Apache Access Logs</h3>
<p>Apache is installed with rotatelogs. This program can be used to rotate the logs after they get too large. However I wanted a few more features. Cronolog will update a symlink everytime it creates a new log file so that you can always have the most recent stats.</p>

<div class="wp_syntax"><div class="code"><pre class="apache"><span style="color: #00007f;">CustomLog</span> <span style="color: #7f007f;">&quot;|/usr/bin/cronolog --symlink=/path/to/access /path/to/%Y/%m/%d/access.log&quot;</span> combined
<span style="color: #00007f;">ErrorLog</span> <span style="color: #7f007f;">&quot;|/usr/bin/cronolog --symlink=/path/to/error /path/to/%Y/%m/%d/error.log&quot;</span></pre></div></div>

<p>CustomLog and ErrorLog directives in apache will let you pipe output to a command. So I put the full path to cronolog and then specified the parameters to cronolog. &#8211;symlink will point the named symlink to the most recent log created with cronolog. After the options, the path to the log location is specified and date formats can be used. I decided to break mine up by day.</p>
<h3>Piping Apache Log info to a Python Script</h3>
<p>Apache can have multiple log locations and log multiple times. So I wrote my own logging script in python that would insert into memcached. Here is the extra line I added to apache:</p>

<div class="wp_syntax"><div class="code"><pre class="apache"><span style="color: #00007f;">CustomLog</span> <span style="color: #7f007f;">&quot;|/path/to/python /path/to/log_cache.py&quot;</span> combined</pre></div></div>

<p>And this is <strong>log_cache.py</strong>:</p>

<div class="wp_syntax"><div class="code"><pre class="python"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">datetime</span> <span style="color: #ff7700;font-weight:bold;">import</span> date
&nbsp;
<span style="color: #dc143c;">sys</span>.<span style="color: black;">path</span> = <span style="color: black;">&#91;</span><span style="color: #483d8b;">'/path/to/project'</span>,<span style="color: black;">&#93;</span> + <span style="color: #dc143c;">sys</span>.<span style="color: black;">path</span>
<span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'DJANGO_SETTINGS_MODULE'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">'myproject.settings'</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">core</span>.<span style="color: black;">cache</span> <span style="color: #ff7700;font-weight:bold;">import</span> cache
&nbsp;
r = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'&quot;GET (?P<span style="color: #000099; font-weight: bold;">\S</span>+) '</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> be_parent<span style="color: black;">&#40;</span>child_pid<span style="color: black;">&#41;</span>:
    exit_status = <span style="color: #dc143c;">os</span>.<span style="color: black;">waitpid</span><span style="color: black;">&#40;</span>child_pid, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> exit_status: <span style="color: #808080; font-style: italic;"># if there's an error, restart the child.</span>
        pid = <span style="color: #dc143c;">os</span>.<span style="color: black;">fork</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> pid:
            be_child<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            be_parent<span style="color: black;">&#40;</span>pid<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> be_child<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
        line = <span style="color: #dc143c;">sys</span>.<span style="color: black;">stdin</span>.<span style="color: #dc143c;">readline</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># wait for apache log data</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> line:
            <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #808080; font-style: italic;"># without error code so everything stops</span>
        log_data<span style="color: black;">&#40;</span>line<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> log_data<span style="color: black;">&#40;</span>data<span style="color: black;">&#41;</span>:
    page = r.<span style="color: black;">search</span><span style="color: black;">&#40;</span>data<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> page:
        key = <span style="color: #483d8b;">'%s%s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>date.<span style="color: black;">today</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, page.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'url'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">try</span>:
            cache.<span style="color: black;">incr</span><span style="color: black;">&#40;</span>key<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">ValueError</span>:
            <span style="color: #808080; font-style: italic;"># add it to the cache for 24 hours</span>
            cache.<span style="color: #008000;">set</span><span style="color: black;">&#40;</span>key, <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">24</span><span style="color: #66cc66;">*</span><span style="color: #ff4500;">60</span><span style="color: #66cc66;">*</span><span style="color: #ff4500;">60</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span>
&nbsp;
pid = <span style="color: #dc143c;">os</span>.<span style="color: black;">fork</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> pid:
    be_child<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">else</span>:
    be_parent<span style="color: black;">&#40;</span>pid<span style="color: black;">&#41;</span></pre></div></div>

<p>A blog post about 
<a  href="http://adam.gomaa.us/blog/2007/sep/23/logging-apache-to-postgresql/" onclick="javascript:pageTracker._trackPageview('/external/adam.gomaa.us/blog/2007/sep/23/logging-apache-to-postgresql/');" >using python to store access records in postgres</a> helped me out a lot. The parent/child processing came from that and fixed a lot of problems I was having before.</p>
<p>The page views are being added to memcached (with 
<a  href="http://docs.djangoproject.com/en/dev/topics/cache/#the-low-level-cache-api" onclick="javascript:pageTracker._trackPageview('/external/docs.djangoproject.com/en/dev/topics/cache/?the-low-level-cache-api');" ><strong>cache.incr()</strong> which is new in django 1.1</a>) for quick retrieval and the logs will still be created by cronolog so no data will be lost when the cache expires. Those logs are used in the next part.</p>
<h3>Parsing the Logs</h3>
<p>The hit counts will expire from the cache after 24 hours so I 
<a  href="http://www.coolsnap.net/kevin/?p=7" onclick="javascript:pageTracker._trackPageview('/external/www.coolsnap.net/kevin/');" >parse the logs</a> once a day and put that information into my database. For this I wrote a 
<a  href="http://docs.djangoproject.com/en/1.0/howto/custom-management-commands/#howto-custom-management-commands" onclick="javascript:pageTracker._trackPageview('/external/docs.djangoproject.com/en/1.0/howto/custom-management-commands/?howto-custom-management-commands');" >django management command</a> (I didn&#8217;t do a management command before because I wasn&#8217;t sure how it would handle the parent and child processes). This command is called by <strong>./manage.py parse_log</strong></p>

<div class="wp_syntax"><div class="code"><pre class="python"><span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">conf</span> <span style="color: #ff7700;font-weight:bold;">import</span> settings
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">contrib</span>.<span style="color: black;">contenttypes</span>.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> ContentType
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">core</span>.<span style="color: black;">cache</span> <span style="color: #ff7700;font-weight:bold;">import</span> cache
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">core</span>.<span style="color: black;">management</span>.<span style="color: black;">base</span> <span style="color: #ff7700;font-weight:bold;">import</span> BaseCommand
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">core</span>.<span style="color: black;">urlresolvers</span> <span style="color: #ff7700;font-weight:bold;">import</span> resolve, Resolver404
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">datetime</span>
<span style="color: #808080; font-style: italic;"># found on page linked above</span>
<span style="color: #ff7700;font-weight:bold;">from</span> apachelogs <span style="color: #ff7700;font-weight:bold;">import</span> ApacheLogFile
<span style="color: #ff7700;font-weight:bold;">from</span> app.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> Model_being_hit
<span style="color: #ff7700;font-weight:bold;">from</span> metrics.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> Hits
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> save_log<span style="color: black;">&#40;</span>alf, date<span style="color: black;">&#41;</span>:
    hits = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
    <span style="color: #808080; font-style: italic;"># loop to sum hits</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> log_line <span style="color: #ff7700;font-weight:bold;">in</span> alf:
        request = log_line.<span style="color: black;">request_line</span>
        request_parts = request.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">' '</span><span style="color: black;">&#41;</span>
        hits<span style="color: black;">&#91;</span>request_parts<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span> = hits.<span style="color: black;">get</span><span style="color: black;">&#40;</span>request_parts<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span> + <span style="color: #ff4500;">1</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> page, views <span style="color: #ff7700;font-weight:bold;">in</span> hits.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">try</span>:
            view, args, kwargs = resolve<span style="color: black;">&#40;</span>page<span style="color: black;">&#41;</span>
            <span style="color: #808080; font-style: italic;"># I check kwargs for something only passed to one app</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #483d8b;">'param'</span> <span style="color: #ff7700;font-weight:bold;">in</span> kwargs:
                a = Model_being_hit.<span style="color: black;">objects</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #008000;">id</span>=kwargs<span style="color: black;">&#91;</span><span style="color: #483d8b;">'id'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
                <span style="color: #ff7700;font-weight:bold;">try</span>:
                    content_type = ContentType.<span style="color: black;">objects</span>.<span style="color: black;">get_for_model</span><span style="color: black;">&#40;</span>a<span style="color: black;">&#41;</span>
                    hit = Hits.<span style="color: black;">objects</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span>
                        date=date,
                        content_type=content_type,
                        object_id=a.<span style="color: #008000;">id</span>,
                    <span style="color: black;">&#41;</span>
                    hit.<span style="color: black;">views</span> = views
                <span style="color: #ff7700;font-weight:bold;">except</span> Hits.<span style="color: black;">DoesNotExist</span>:
                    hit = Hits<span style="color: black;">&#40;</span>date=date, views=views, content_object=a<span style="color: black;">&#41;</span>
                hit.<span style="color: black;">save</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">except</span>:
            <span style="color: #808080; font-style: italic;"># something not in urls file like static files</span>
            <span style="color: #ff7700;font-weight:bold;">pass</span>
<span style="color: #ff7700;font-weight:bold;">class</span> Command<span style="color: black;">&#40;</span>BaseCommand<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> handle<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>options<span style="color: black;">&#41;</span>:
        day = <span style="color: #dc143c;">datetime</span>.<span style="color: black;">date</span>.<span style="color: black;">today</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        day = day - <span style="color: #dc143c;">datetime</span>.<span style="color: black;">timedelta</span><span style="color: black;">&#40;</span>days=<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
        alf = ApacheLogFile<span style="color: black;">&#40;</span><span style="color: #483d8b;">'%s/%s/%s/%s/access.log'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>
            settings.<span style="color: black;">ACCESS_LOG_LOCATION</span>,
            day.<span style="color: black;">year</span>,
            day.<span style="color: black;">strftime</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'%m'</span><span style="color: black;">&#41;</span>, <span style="color: #808080; font-style: italic;">#month</span>
            day.<span style="color: black;">strftime</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'%d'</span><span style="color: black;">&#41;</span>, <span style="color: #808080; font-style: italic;">#day</span>
        <span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        save_log<span style="color: black;">&#40;</span>alf, day<span style="color: black;">&#41;</span></pre></div></div>

<p>I use 
<a  href="http://docs.djangoproject.com/en/dev/topics/http/urls/#resolve" onclick="javascript:pageTracker._trackPageview('/external/docs.djangoproject.com/en/dev/topics/http/urls/?resolve');" >django.core.urlresolvers.resolve</a> so that I can use my urls file and I don&#8217;t have to repeat myself.</p>
<p><strong>Hits</strong> is a django model I created with a few fields for storing date and views. It uses the 
<a  href="http://codespatter.com/2009/01/15/how-to-write-reusable-apps-for-pinax-and-django/">content types framework</a> so that it can be tied to any of my django models.</p>

<div class="wp_syntax"><div class="code"><pre class="python"><span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">contrib</span>.<span style="color: black;">contenttypes</span>        <span style="color: #ff7700;font-weight:bold;">import</span> generic
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">contrib</span>.<span style="color: black;">contenttypes</span>.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> ContentType
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">db</span> <span style="color: #ff7700;font-weight:bold;">import</span> models
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Hits<span style="color: black;">&#40;</span>models.<span style="color: black;">Model</span><span style="color: black;">&#41;</span>:
    date        = models.<span style="color: black;">DateField</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    views       = models.<span style="color: black;">IntegerField</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># to add to any model</span>
    content_type   = models.<span style="color: black;">ForeignKey</span><span style="color: black;">&#40;</span>ContentType<span style="color: black;">&#41;</span>
    object_id      = models.<span style="color: black;">PositiveIntegerField</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    content_object = generic.<span style="color: black;">GenericForeignKey</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'content_type'</span>, <span style="color: #483d8b;">'object_id'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__unicode__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;%s hits on %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">views</span>, <span style="color: #008000;">self</span>.<span style="color: black;">date</span><span style="color: black;">&#41;</span></pre></div></div>

<p>This was added to my cron with <strong>crontab -e</strong></p>

<div class="wp_syntax"><div class="code"><pre>#every morning on the first minute
1 0 * * * /path/to/python /path/to/manage.py parse_log &gt; /dev/null</pre></div></div>

<h3>Displaying the Hits</h3>
<p>On my models I added a couple methods that would look up the info in the cache or database.</p>

<div class="wp_syntax"><div class="code"><pre class="python">    @<span style="color: #008000;">property</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> hits_today<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">datetime</span> <span style="color: #ff7700;font-weight:bold;">import</span> date
        <span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">core</span>.<span style="color: black;">cache</span> <span style="color: #ff7700;font-weight:bold;">import</span> cache
        key = <span style="color: #483d8b;">'%s%s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>date.<span style="color: black;">today</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">self</span>.<span style="color: black;">get_absolute_url</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> cache.<span style="color: black;">get</span><span style="color: black;">&#40;</span>key<span style="color: black;">&#41;</span>
&nbsp;
    @<span style="color: #008000;">property</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> hits<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">from</span> metrics.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> Hits
        <span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">contrib</span>.<span style="color: black;">contenttypes</span>.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> ContentType
        content_type = ContentType.<span style="color: black;">objects</span>.<span style="color: black;">get_for_model</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
        hits = Hits.<span style="color: black;">objects</span>.<span style="color: #008000;">filter</span><span style="color: black;">&#40;</span>
            content_type=content_type,
            object_id=<span style="color: #008000;">self</span>.<span style="color: #008000;">id</span>,
        <span style="color: black;">&#41;</span>.<span style="color: black;">order_by</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'-date'</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> hits</pre></div></div>

<p>The <strong>hits_today</strong> method requires that you define 
<a  href="http://docs.djangoproject.com/en/dev/ref/models/instances/#get-absolute-url" onclick="javascript:pageTracker._trackPageview('/external/docs.djangoproject.com/en/dev/ref/models/instances/?get-absolute-url');" >get_absolute_url</a> which is useful in other places as well. @property is a decorator that makes it possible to access the data with object.hits and leave off the parenthesis.</p>
<p>The <strong>hits</strong> method uses the content type framework again to look up the hits in the database.</p>
<h3>Just the Basics</h3>
<p>There is a lot more that can be done with this. This barely touches the raw data available in the logs. A few ways I&#8217;ve already started improving this is to not include known bots as hits, check the referrer to see where traffic is coming from, and save the keywords used in search engines.</p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fcodespatter.com%2F2009%2F09%2F02%2Fhow-to-display-realtime-traffic-analytics%2F';
  addthis_title  = 'How+to+Display+Realtime+Traffic+Analytics';
  addthis_pub    = 'gallard';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>


<p>Related posts:</p><ol><li><a href='http://codespatter.com/2009/04/23/how-to-speed-up-your-django-sites/' rel='bookmark' title='Permanent Link: How to Speed up Your Django Sites with NginX, Memcached, and django-compress'>How to Speed up Your Django Sites with NginX, Memcached, and django-compress</a> <small>A lot of these steps will speed up any kind...</small></li><li><a href='http://codespatter.com/2009/07/08/python-projects-in-users-home-directories-with-wsgi/' rel='bookmark' title='Permanent Link: Python Projects in Users&#8217; Home Directories with wsgi'>Python Projects in Users&#8217; Home Directories with wsgi</a> <small>Letting users put static files and php files in a...</small></li><li><a href='http://codespatter.com/2009/01/15/how-to-write-reusable-apps-for-pinax-and-django/' rel='bookmark' title='Permanent Link: How to Write Reusable Apps for Pinax and Django'>How to Write Reusable Apps for Pinax and Django</a> <small> Pinax is a collection of reusable django apps that...</small></li></ol>]]></content:encoded>
			<wfw:commentRss>http://codespatter.com/2009/09/02/how-to-display-realtime-traffic-analytics/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Python Projects in Users&#8217; Home Directories with wsgi</title>
		<link>http://codespatter.com/2009/07/08/python-projects-in-users-home-directories-with-wsgi/</link>
		<comments>http://codespatter.com/2009/07/08/python-projects-in-users-home-directories-with-wsgi/#comments</comments>
		<pubDate>Wed, 08 Jul 2009 14:27:12 +0000</pubDate>
		<dc:creator>Greg Allard</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Server Administration]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[wsgi]]></category>

		<guid isPermaLink="false">http://codespatter.com/?p=484</guid>
		<description><![CDATA[Letting users put static files and php files in a public_html folder in their home directory has been a common convention for some time. I created a way for users to have a public_python folder that will allow for python projects.
In the apache configuration files I created some regular expression patterns that will look for [...]


Related posts:<ol><li><a href='http://codespatter.com/2009/04/10/how-to-add-locations-to-python-path-for-reusable-django-apps/' rel='bookmark' title='Permanent Link: How to Add Locations to Python Path for Reusable Django Apps'>How to Add Locations to Python Path for Reusable Django Apps</a> <small>In my previous post I talk about reusable apps, but...</small></li><li><a href='http://codespatter.com/2009/04/01/getting-basecamp-api-working-with-python/' rel='bookmark' title='Permanent Link: Getting Basecamp API Working with Python'>Getting Basecamp API Working with Python</a> <small>I found one library that was linked everywhere, but it...</small></li><li><a href='http://codespatter.com/2008/10/15/setting-up-apache2-mod_python-mysql-and-django-on-debian-lenny-or-ubuntu-hardy-heron/' rel='bookmark' title='Permanent Link: Setting up Apache2, mod_python, MySQL, and Django on Debian Lenny or Ubuntu Hardy Heron'>Setting up Apache2, mod_python, MySQL, and Django on Debian Lenny or Ubuntu Hardy Heron</a> <small>Both Debian and Ubuntu make it really simple to get...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p>Letting users put static files and php files in a public_html folder in their home directory has been a common convention for some time. I created a way for users to have a public_python folder that will allow for python projects.</p>
<p>In the apache configuration files I created some regular expression patterns that will look for a wsgi file based on the url requested. To serve this url: <strong>http://domain/~user/p/myproject</strong>, the server will look for this wsgi file: <strong>/home/user/public_python/myproject/deploy/myproject.wsgi</strong></p>
<p>It is set up to run wsgi in daemon mode so that each user can touch their own wsgi file to restart their project instead of needing to reload the apache config and inconvenience everyone.</p>
<p>This is the code I added to the apache configuration (in a virtual host, other configs might be different):</p>

<div class="wp_syntax"><div class="code"><pre class="apache"><span style="color: #00007f;">RewriteEngine</span> <span style="color: #0000ff;">On</span>
<span style="color: #00007f;">RewriteCond</span> %<span style="color: #66cc66;">&#123;</span>REQUEST_URI<span style="color: #66cc66;">&#125;</span> ^/~<span style="color: #66cc66;">&#40;</span>\w+<span style="color: #66cc66;">&#41;</span>/p/<span style="color: #66cc66;">&#40;</span>\w+<span style="color: #66cc66;">&#41;</span>/<span style="color: #66cc66;">&#40;</span>.*<span style="color: #66cc66;">&#41;</span>
<span style="color: #00007f;">RewriteRule</span> . - <span style="color: #66cc66;">&#91;</span>E=python_project_name:%<span style="color: #ff0000;">2</span><span style="color: #66cc66;">&#93;</span>
&nbsp;
WSGIScriptAliasMatch ^/~<span style="color: #66cc66;">&#40;</span>\w+<span style="color: #66cc66;">&#41;</span>/p/<span style="color: #66cc66;">&#40;</span>\w+<span style="color: #66cc66;">&#41;</span>  /home/$<span style="color: #ff0000;">1</span>/public_python/$<span style="color: #ff0000;">2</span>/deploy/$<span style="color: #ff0000;">2</span>.wsgi
WSGIDaemonProcess wsgi_processes.%<span style="color: #66cc66;">&#123;</span>ENV:python_project_name<span style="color: #66cc66;">&#125;</span>
processes=<span style="color: #ff0000;">2</span> threads=<span style="color: #ff0000;">15</span>
WSGIProcessGroup wsgi_processes.%<span style="color: #66cc66;">&#123;</span>ENV:python_project_name<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #00007f;">AliasMatch</span> ^/~<span style="color: #66cc66;">&#40;</span>\w+<span style="color: #66cc66;">&#41;</span>/p/<span style="color: #66cc66;">&#40;</span>\w+<span style="color: #66cc66;">&#41;</span>/<span style="color: #00007f;">files</span><span style="color: #66cc66;">&#40;</span>.*<span style="color: #66cc66;">&#41;</span> /home/$<span style="color: #ff0000;">1</span>/public_python/$<span style="color: #ff0000;">2</span>/<span style="color: #00007f;">files</span>$<span style="color: #ff0000;">3</span>
&lt;LocationMatch ^/~<span style="color: #66cc66;">&#40;</span>\w+<span style="color: #66cc66;">&#41;</span>/p/<span style="color: #66cc66;">&#40;</span>\w+<span style="color: #66cc66;">&#41;</span>/<span style="color: #00007f;">files</span><span style="color: #66cc66;">&#40;</span>.*<span style="color: #66cc66;">&#41;</span>&gt;
       <span style="color: #00007f;">SetHandler</span> <span style="color: #0000ff;">none</span>
&lt;/LocationMatch&gt;
&nbsp;
<span style="color: #00007f;">AliasMatch</span> ^/~<span style="color: #66cc66;">&#40;</span>\w+<span style="color: #66cc66;">&#41;</span>/p/<span style="color: #66cc66;">&#40;</span>\w+<span style="color: #66cc66;">&#41;</span>/media<span style="color: #66cc66;">&#40;</span>.*<span style="color: #66cc66;">&#41;</span> /home/$<span style="color: #ff0000;">1</span>/public_python/$<span style="color: #ff0000;">2</span>/media$<span style="color: #ff0000;">3</span>
&lt;LocationMatch ^/~<span style="color: #66cc66;">&#40;</span>\w+<span style="color: #66cc66;">&#41;</span>/p/<span style="color: #66cc66;">&#40;</span>\w+<span style="color: #66cc66;">&#41;</span>/media<span style="color: #66cc66;">&#40;</span>.*<span style="color: #66cc66;">&#41;</span>&gt;
       <span style="color: #00007f;">SetHandler</span> <span style="color: #0000ff;">none</span>
&lt;/LocationMatch&gt;</pre></div></div>

<p>This will also serve two directories statically for images, css, and javascript. For one of them, I always make a symbolic link to the django admin media and tell my settings file to use that.</p>

<div class="wp_syntax"><div class="code"><pre class="bash"><span style="color: #c20cb9; font-weight: bold;">ln</span> -s <span style="color: #000000; font-weight: bold;">/</span>path<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span>django<span style="color: #000000; font-weight: bold;">/</span>contrib<span style="color: #000000; font-weight: bold;">/</span>admin<span style="color: #000000; font-weight: bold;">/</span>media media</pre></div></div>

<h3>To use this for a django project</h3>
<p>This is a sample wsgi file to use for a django project. Username and project_name will need to be replaced. I&#8217;m also adding an apps folder to the path following 
<a  href="http://codespatter.com/2009/01/15/how-to-write-reusable-apps-for-pinax-and-django/">the style I mention in my reusable apps post</a>.</p>

<div class="wp_syntax"><div class="code"><pre class="python"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
&nbsp;
<span style="color: #dc143c;">sys</span>.<span style="color: black;">path</span> = <span style="color: black;">&#91;</span><span style="color: #483d8b;">'/home/username/public_python/'</span>, <span style="color: #483d8b;">'/home/username/public_python/project_name/apps'</span><span style="color: black;">&#93;</span> + <span style="color: #dc143c;">sys</span>.<span style="color: black;">path</span>
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">core</span>.<span style="color: black;">handlers</span>.<span style="color: black;">wsgi</span> <span style="color: #ff7700;font-weight:bold;">import</span> WSGIHandler
&nbsp;
<span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'DJANGO_SETTINGS_MODULE'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">'project_name.settings'</span>
application = WSGIHandler<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>I&#8217;ve been using this for a couple weeks and it&#8217;s working great for me. If you use it, I&#8217;d like to know how it works out for you. Let me know in the comments.</p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fcodespatter.com%2F2009%2F07%2F08%2Fpython-projects-in-users-home-directories-with-wsgi%2F';
  addthis_title  = 'Python+Projects+in+Users%26%238217%3B+Home+Directories+with+wsgi';
  addthis_pub    = 'gallard';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>


<p>Related posts:</p><ol><li><a href='http://codespatter.com/2009/04/10/how-to-add-locations-to-python-path-for-reusable-django-apps/' rel='bookmark' title='Permanent Link: How to Add Locations to Python Path for Reusable Django Apps'>How to Add Locations to Python Path for Reusable Django Apps</a> <small>In my previous post I talk about reusable apps, but...</small></li><li><a href='http://codespatter.com/2009/04/01/getting-basecamp-api-working-with-python/' rel='bookmark' title='Permanent Link: Getting Basecamp API Working with Python'>Getting Basecamp API Working with Python</a> <small>I found one library that was linked everywhere, but it...</small></li><li><a href='http://codespatter.com/2008/10/15/setting-up-apache2-mod_python-mysql-and-django-on-debian-lenny-or-ubuntu-hardy-heron/' rel='bookmark' title='Permanent Link: Setting up Apache2, mod_python, MySQL, and Django on Debian Lenny or Ubuntu Hardy Heron'>Setting up Apache2, mod_python, MySQL, and Django on Debian Lenny or Ubuntu Hardy Heron</a> <small>Both Debian and Ubuntu make it really simple to get...</small></li></ol>]]></content:encoded>
			<wfw:commentRss>http://codespatter.com/2009/07/08/python-projects-in-users-home-directories-with-wsgi/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>How to Speed up Your Django Sites with NginX, Memcached, and django-compress</title>
		<link>http://codespatter.com/2009/04/23/how-to-speed-up-your-django-sites/</link>
		<comments>http://codespatter.com/2009/04/23/how-to-speed-up-your-django-sites/#comments</comments>
		<pubDate>Thu, 23 Apr 2009 14:22:30 +0000</pubDate>
		<dc:creator>Greg Allard</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Server Administration]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://codespatter.com/?p=389</guid>
		<description><![CDATA[A lot of these steps will speed up any kind of application, not just django projects, but there are a few django specific things. Everything has been tested on 
IvyLees which is running in a Debian/Ubuntu environment.
These three simple steps will speed up your server and allow it to handle more traffic.


Reducing the Number of [...]


Related posts:<ol><li><a href='http://codespatter.com/2008/09/22/static-files-in-django-on-production-and-development/' rel='bookmark' title='Permanent Link: Static Files in Django on Production and Development'>Static Files in Django on Production and Development</a> <small>Update 2009-03-25 I realize why this isn&#8217;t needed. If your...</small></li><li><a href='http://codespatter.com/2009/09/02/how-to-display-realtime-traffic-analytics/' rel='bookmark' title='Permanent Link: How to Display Realtime Traffic Analytics'>How to Display Realtime Traffic Analytics</a> <small>Users of Presskit&#8217;n have been asking for traffic statistics on...</small></li><li><a href='http://codespatter.com/2009/07/08/python-projects-in-users-home-directories-with-wsgi/' rel='bookmark' title='Permanent Link: Python Projects in Users&#8217; Home Directories with wsgi'>Python Projects in Users&#8217; Home Directories with wsgi</a> <small>Letting users put static files and php files in a...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p>A lot of these steps will speed up any kind of application, not just django projects, but there are a few django specific things. Everything has been tested on 
<a  href="http://ivylees.com" onclick="javascript:pageTracker._trackPageview('/external/ivylees.com');" >IvyLees</a> which is running in a Debian/Ubuntu environment.</p>
<p>These three simple steps will speed up your server and allow it to handle more traffic.</p>
<ul>
<li>
<a  href="#http-requests">Reducing the Number of HTTP Requests</a></li>
<li>
<a  href="#memcached">Caching</a></li>
<li>
<a  href="#nginx">Using a lightweight front end server</a></li>
</ul>
<h3 id="http-requests">Reducing the Number of HTTP Requests</h3>
<p>Yahoo has developed a 
<a  href="http://www.mozilla.com/firefox/" onclick="javascript:pageTracker._trackPageview('/external/www.mozilla.com/firefox/');" >firefox</a> extension called 
<a  href="http://developer.yahoo.com/yslow/" onclick="javascript:pageTracker._trackPageview('/external/developer.yahoo.com/yslow/');" >YSlow</a>. It analyzes all of the traffic from a website and gives a score on a few categories where improvements can be made.</p>
<p>It recommends reducing all of your css files into one file and all of your js files into one file or as few as possible. There is a pluggable, open source django application available to help with that task. After setting up 
<a  href="http://code.google.com/p/django-compress/" onclick="javascript:pageTracker._trackPageview('/external/code.google.com/p/django-compress/');" >django-compress</a>, a website will have css and js files that are minified (excess white space and characters are removed to reduce file size). The application will also give the files version numbers so that they can be cached by the web browser and won&#8217;t need to be downloaded again until a change is made and a new version of the file is created. 
<a  href="#far_future_expires">How to setup the server to set a far future expiration is shown below in the lightweight server section</a>.</p>
<h3 id="memcached">Setting up Memcached</h3>
<p>Django makes it really simple to set up caching backends and memcached is easy to install.</p>

<div class="wp_syntax"><div class="code"><pre>sudo aptitude install memcached, python-setuptools</pre></div></div>

<p>We will need setuptools so that we can do the following command.</p>

<div class="wp_syntax"><div class="code"><pre>sudo easy_install python-memcached</pre></div></div>

<p>Once that is done you can start the memcached server by doing the following:</p>

<div class="wp_syntax"><div class="code"><pre>sudo memcached -d -u www-data -p 11211 -m 64</pre></div></div>

<p>-d will start it in daemon mode, -u is the user for it to run as, -p is the port, and -m is the maximum number of megabytes of memory to use.</p>
<p>Now open up the settings.py file for your project and add the following line:</p>

<div class="wp_syntax"><div class="code"><pre class="python">CACHE_BACKEND = <span style="color: #483d8b;">'memcached://127.0.0.1:11211/'</span></pre></div></div>

<p>Find the MIDDLEWARE_CLASSES section and add this to the beginning of the list:</p>

<div class="wp_syntax"><div class="code"><pre class="python">    <span style="color: #483d8b;">'django.middleware.cache.UpdateCacheMiddleware'</span>,</pre></div></div>

<p>and this to the end of the list:</p>

<div class="wp_syntax"><div class="code"><pre class="python">    <span style="color: #483d8b;">'django.middleware.cache.FetchFromCacheMiddleware'</span>,</pre></div></div>

<p>For more about caching with django see the 
<a  href="http://docs.djangoproject.com/en/dev/topics/cache/" onclick="javascript:pageTracker._trackPageview('/external/docs.djangoproject.com/en/dev/topics/cache/');" >django docs on caching</a>. You can reload the server now to try it out.</p>

<div class="wp_syntax"><div class="code"><pre>sudo /etc/init.d/apache2 reload</pre></div></div>

<p>To make sure that memcached is set up correctly you can telnet into it and get some statistics.</p>

<div class="wp_syntax"><div class="code"><pre>telnet localhost 11211</pre></div></div>

<p>Once you are in type <strong>stats</strong> and it will show some information (press ctrl ] and then ctrl d to exit). If there are too many zeroes, it either isn&#8217;t working or you haven&#8217;t visited your site since the caching was set up. See 
<a  href="http://www.danga.com/memcached/" onclick="javascript:pageTracker._trackPageview('/external/www.danga.com/memcached/');" >the memcached site</a> for more information.</p>
<h3 id="nginx">Don&#8217;t Use Apache for Static Files</h3>
<p>Apache has some overhead involved that makes it good for serving php, python, or ruby applications, but you do not need that for static files like your images, style sheets, and javascript. There are a few options for lightweight servers that you can put in front of apache to handle the static files. 
<a  href="http://www.lighttpd.net/" onclick="javascript:pageTracker._trackPageview('/external/www.lighttpd.net/');" >Lighttpd (lighty)</a> and 
<a  href="http://nginx.net/" onclick="javascript:pageTracker._trackPageview('/external/nginx.net/');" >nginx (engine x)</a> are two good options. Adding this layer in front of your application will act as an application firewall so there is a security bonus to the speed bonus. </p>
<p>There is this guide to 
<a  href="http://www.ventanazul.com/webzine/tutorials/django-deployment-guide-ubuntu" onclick="javascript:pageTracker._trackPageview('/external/www.ventanazul.com/webzine/tutorials/django-deployment-guide-ubuntu');" >install a django setup with nginx and apache from scratch</a>. If you followed 
<a  href="http://codespatter.com/2008/10/15/setting-up-apache2-mod_python-mysql-and-django-on-debian-lenny-or-ubuntu-hardy-heron/">my guide to set up your server</a> or already have apache set up for your application, then there are a few steps to get nginx handling your static files.</p>

<div class="wp_syntax"><div class="code"><pre>sudo aptitude install nginx</pre></div></div>

<p>Edit the config file for your site (sudo nano /etc/apache2/sites-available/default) and change the port from 80 to 8080 and change the ip address (might be *) to 127.0.0.1. The lines will look like the following</p>

<div class="wp_syntax"><div class="code"><pre>NameVirtualHost 127.0.0.1:8080
&lt;VirtualHost 127.0.0.1:8080&gt;</pre></div></div>

<p>Also edit the ports.conf file (sudo nano /etc/apache2/ports.conf) so that it will listen on 8080.</p>

<div class="wp_syntax"><div class="code"><pre>Listen 8080</pre></div></div>

<p>Don&#8217;t restart the server yet, you want to configure nginx first. Edit the default nginx config file (sudo nano /etc/nginx/sites-available/default) and find where it says</p>

<div class="wp_syntax"><div class="code"><pre>        location / {
               root   /var/www/nginx-default;
               index  index.html index.htm;
        }</pre></div></div>

<p>and replace it with</p>

<div class="wp_syntax"><div class="code"><pre>location / {
    proxy_pass http://192.168.0.180:8080;
    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    client_max_body_size 10m;
    client_body_buffer_size 128k;
    proxy_connect_timeout 90;
    proxy_send_timeout 90;
    proxy_read_timeout 90;
    proxy_buffer_size 4k;
    proxy_buffers 4 32k;
    proxy_busy_buffers_size 64k;
    proxy_temp_file_write_size 64k; 
}
location /files/ {
    root /var/www/myproject/;
    expires max;
}</pre></div></div>

<p>/files/ is where I&#8217;ve stored all of my static files and /var/www/myproject/ is where my project lives and it contains the files directory. </p>
<p id="far_future_expires"><strong>Set static files to expire far in the future</strong></p>
<p>expires max; will tell your users&#8217; browsers to cache the files from that directory for a long time. Only use that if you are use those files won&#8217;t change. You can use expires 24h; if you aren&#8217;t sure.</p>
<p id="far_future_expires"><strong>Configure gzip</strong></p>
<p>Edit the nginx configuration to use gzip on all of your static files (sudo nano /etc/nginx/nginx.conf). Where it says gzip on; make sure it looks like the following:</p>

<div class="wp_syntax"><div class="code"><pre>    gzip  on;
    gzip_comp_level 2;
    gzip_proxied any;
    gzip_types      text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;</pre></div></div>

<p>The servers should be ready to be restarted.</p>

<div class="wp_syntax"><div class="code"><pre>sudo /etc/init.d/apache2 reload
sudo /etc/init.d/nginx reload</pre></div></div>

<p>If you are having any problems I suggest reading through 
<a  href="http://www.ventanazul.com/webzine/tutorials/django-deployment-guide-ubuntu" onclick="javascript:pageTracker._trackPageview('/external/www.ventanazul.com/webzine/tutorials/django-deployment-guide-ubuntu');" >this guide</a> and seeing if you have something set up differently.</p>
<h3>Speedy Django Sites</h3>
<p>Those three steps should speed up your server and allow for more simultaneous visitors. There is a lot more that can be done, but getting these three easy things out of the way first is a good start.</p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fcodespatter.com%2F2009%2F04%2F23%2Fhow-to-speed-up-your-django-sites%2F';
  addthis_title  = 'How+to+Speed+up+Your+Django+Sites+with+NginX%2C+Memcached%2C+and+django-compress';
  addthis_pub    = 'gallard';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>


<p>Related posts:</p><ol><li><a href='http://codespatter.com/2008/09/22/static-files-in-django-on-production-and-development/' rel='bookmark' title='Permanent Link: Static Files in Django on Production and Development'>Static Files in Django on Production and Development</a> <small>Update 2009-03-25 I realize why this isn&#8217;t needed. If your...</small></li><li><a href='http://codespatter.com/2009/09/02/how-to-display-realtime-traffic-analytics/' rel='bookmark' title='Permanent Link: How to Display Realtime Traffic Analytics'>How to Display Realtime Traffic Analytics</a> <small>Users of Presskit&#8217;n have been asking for traffic statistics on...</small></li><li><a href='http://codespatter.com/2009/07/08/python-projects-in-users-home-directories-with-wsgi/' rel='bookmark' title='Permanent Link: Python Projects in Users&#8217; Home Directories with wsgi'>Python Projects in Users&#8217; Home Directories with wsgi</a> <small>Letting users put static files and php files in a...</small></li></ol>]]></content:encoded>
			<wfw:commentRss>http://codespatter.com/2009/04/23/how-to-speed-up-your-django-sites/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Setting up Apache2, mod_python, MySQL, and Django on Debian Lenny or Ubuntu Hardy Heron</title>
		<link>http://codespatter.com/2008/10/15/setting-up-apache2-mod_python-mysql-and-django-on-debian-lenny-or-ubuntu-hardy-heron/</link>
		<comments>http://codespatter.com/2008/10/15/setting-up-apache2-mod_python-mysql-and-django-on-debian-lenny-or-ubuntu-hardy-heron/#comments</comments>
		<pubDate>Wed, 15 Oct 2008 14:46:46 +0000</pubDate>
		<dc:creator>Greg Allard</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Server Administration]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[Debian]]></category>
		<category><![CDATA[mod_python]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://codespatter.com/?p=141</guid>
		<description><![CDATA[Both Debian and Ubuntu make it really simple to get a server up and running. I was trying a few different Machine Images on Amazon and I found myself repeating a lot of things so I wanted to put them here for reference for those who might find it useful.
With a fresh image, the first [...]


Related posts:<ol><li><a href='http://codespatter.com/2008/07/02/tips-for-mysql-to-postgresql-switch/' rel='bookmark' title='Permanent Link: Tips for MySQL to PostgreSQL Switch'>Tips for MySQL to PostgreSQL Switch</a> <small>If you&#8217;ve decided to move a few tables from MySQL...</small></li><li><a href='http://codespatter.com/2009/07/08/python-projects-in-users-home-directories-with-wsgi/' rel='bookmark' title='Permanent Link: Python Projects in Users&#8217; Home Directories with wsgi'>Python Projects in Users&#8217; Home Directories with wsgi</a> <small>Letting users put static files and php files in a...</small></li><li><a href='http://codespatter.com/2008/05/06/how-to-use-triggers-to-track-changes-in-mysql/' rel='bookmark' title='Permanent Link: How To Use Triggers to Track Changes in MySQL'>How To Use Triggers to Track Changes in MySQL</a> <small>Setting constraints and rules in the database is better than...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p>Both Debian and Ubuntu make it really simple to get a server up and running. I was trying a few different Machine Images on Amazon and I found myself repeating a lot of things so I wanted to put them here for reference for those who might find it useful.</p>
<p>With a fresh image, the first thing to do is update apt-get.</p>

<div class="wp_syntax"><div class="code"><pre>apt-get update &amp;&amp; apt-get upgrade -y</pre></div></div>

<p>Then grab all of the software to use.</p>

<div class="wp_syntax"><div class="code"><pre>apt-get install -y xfsprogs mysql-server  apache2  libapache2-mod-python  python-mysqldb  python-imaging  python-django  subversion php5  phpmyadmin</pre></div></div>

<p>xfsprogs is for formatting an Elastic Block Store volume and may not be needed in all cases.</p>
<p>I like to check out the latest version of Django from their repository, it makes it easier to update it later. This also starts a project named myproject (this name is used later).</p>

<div class="wp_syntax"><div class="code"><pre>cd /usr/lib/python2.5/site-packages
svn co http://code.djangoproject.com/svn/django/trunk/django django
ln -s /usr/lib/python2.5/site-packages/django/bin/django-admin.py /usr/local/bin
cd /var/www
django-admin.py startproject myproject</pre></div></div>

<p>Now to edit the apache config to tell it about our project.</p>

<div class="wp_syntax"><div class="code"><pre>cd /etc/apache2
nano httpd.conf</pre></div></div>

<p>Add the following to set up python to run the django files and php to run the phpmyadmin files. There is also an example of serving static files. Change where it says myproject if you used a different name.</p>

<div class="wp_syntax"><div class="code"><pre class="xml"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Location</span> <span style="color: #ff0000;">&quot;/&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span>
    SetHandler python-program
    PythonHandler django.core.handlers.modpython
    SetEnv DJANGO_SETTINGS_MODULE myproject.settings
    PythonOption django.root /myproject
    PythonDebug On
    PythonPath &quot;['/var/www'] + sys.path&quot;
<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Location<span style="font-weight: bold; color: black;">&gt;</span></span></span>
&nbsp;
&nbsp;
Alias /adm_media/ /usr/lib/python2.5/site-packages/django/contrib/admin/media/
<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Location</span> <span style="color: #ff0000;">&quot;/adm_media/&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span>
    SetHandler None
<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Location<span style="font-weight: bold; color: black;">&gt;</span></span></span>
&nbsp;
Alias /files/ /var/www/myproject/files/
<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Location</span> <span style="color: #ff0000;">&quot;/files/&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span>
    SetHandler None
<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Location<span style="font-weight: bold; color: black;">&gt;</span></span></span>
&nbsp;
Alias /phpmyadmin/ /usr/share/phpmyadmin/
<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Location</span> <span style="color: #ff0000;">&quot;/phpmyadmin/&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span>
    SetHandler None
<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Location<span style="font-weight: bold; color: black;">&gt;</span></span></span></pre></div></div>

<p>Restart apache for it to use the new configuration.</p>

<div class="wp_syntax"><div class="code"><pre>/etc/init.d/apache2 restart</pre></div></div>

<p>The only thing left to do is set up the database. If Ubuntu had you set up a root password already, add -p to the end of the following command to use it.</p>

<div class="wp_syntax"><div class="code"><pre>mysql</pre></div></div>

<p>There are some users in mysql without username, it is best to remove those.</p>

<div class="wp_syntax"><div class="code"><pre>drop user ''@'localhost';</pre></div></div>

<p>Do that for each host that has a blank username. Use the following to see all users.</p>

<div class="wp_syntax"><div class="code"><pre>SELECT user, host FROM mysql.user;</pre></div></div>

<p>Create a database and add a user.</p>

<div class="wp_syntax"><div class="code"><pre>CREATE DATABASE db_name;
GRANT ALL ON db_name.* to user_name WITH GRANT OPTION;
SET PASSWORD FOR user_name = password('psswdhere');</pre></div></div>

<p>If root doesn&#8217;t have a password yet, use the above commant with root as the username.</p>
<p>Amazon has a page about 
<a  href="http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1663" onclick="javascript:pageTracker._trackPageview('/external/developer.amazonwebservices.com/connect/entry.jspa');" >how to use EBS with MySQL</a>, but 
<a  href="http://developer.amazonwebservices.com/connect/thread.jspa?messageID=99070" onclick="javascript:pageTracker._trackPageview('/external/developer.amazonwebservices.com/connect/thread.jspa');" >there are reported issues with using Debian Lenny and EBS</a>.</p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fcodespatter.com%2F2008%2F10%2F15%2Fsetting-up-apache2-mod_python-mysql-and-django-on-debian-lenny-or-ubuntu-hardy-heron%2F';
  addthis_title  = 'Setting+up+Apache2%2C+mod_python%2C+MySQL%2C+and+Django+on+Debian+Lenny+or+Ubuntu+Hardy+Heron';
  addthis_pub    = 'gallard';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>


<p>Related posts:</p><ol><li><a href='http://codespatter.com/2008/07/02/tips-for-mysql-to-postgresql-switch/' rel='bookmark' title='Permanent Link: Tips for MySQL to PostgreSQL Switch'>Tips for MySQL to PostgreSQL Switch</a> <small>If you&#8217;ve decided to move a few tables from MySQL...</small></li><li><a href='http://codespatter.com/2009/07/08/python-projects-in-users-home-directories-with-wsgi/' rel='bookmark' title='Permanent Link: Python Projects in Users&#8217; Home Directories with wsgi'>Python Projects in Users&#8217; Home Directories with wsgi</a> <small>Letting users put static files and php files in a...</small></li><li><a href='http://codespatter.com/2008/05/06/how-to-use-triggers-to-track-changes-in-mysql/' rel='bookmark' title='Permanent Link: How To Use Triggers to Track Changes in MySQL'>How To Use Triggers to Track Changes in MySQL</a> <small>Setting constraints and rules in the database is better than...</small></li></ol>]]></content:encoded>
			<wfw:commentRss>http://codespatter.com/2008/10/15/setting-up-apache2-mod_python-mysql-and-django-on-debian-lenny-or-ubuntu-hardy-heron/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Server ATTACK</title>
		<link>http://codespatter.com/2007/05/04/server-attack/</link>
		<comments>http://codespatter.com/2007/05/04/server-attack/#comments</comments>
		<pubDate>Fri, 04 May 2007 21:20:20 +0000</pubDate>
		<dc:creator>Greg Allard</dc:creator>
				<category><![CDATA[Server Administration]]></category>

		<guid isPermaLink="false">http://codespatter.com/?p=5</guid>
		<description><![CDATA[I got an e-mail saying that a server I administrate was attacked. There weren&#8217;t any details in the message, so later I find out that there was porn posted on the forums. Sounds like spam bots found the phpBB installation and had some fun.
OMG take the server offline immediately!!

  addthis_url    = [...]


Related posts:<ol><li><a href='http://codespatter.com/2009/04/23/how-to-speed-up-your-django-sites/' rel='bookmark' title='Permanent Link: How to Speed up Your Django Sites with NginX, Memcached, and django-compress'>How to Speed up Your Django Sites with NginX, Memcached, and django-compress</a> <small>A lot of these steps will speed up any kind...</small></li><li><a href='http://codespatter.com/2009/07/08/python-projects-in-users-home-directories-with-wsgi/' rel='bookmark' title='Permanent Link: Python Projects in Users&#8217; Home Directories with wsgi'>Python Projects in Users&#8217; Home Directories with wsgi</a> <small>Letting users put static files and php files in a...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p>I got an e-mail saying that a server I administrate was attacked. There weren&#8217;t any details in the message, so later I find out that there was porn posted on the forums. Sounds like spam bots found the phpBB installation and had some fun.</p>
<p><strong>OMG take the server offline immediately!!</strong></p>
<script type="text/javascript">
  addthis_url    = 'http%3A%2F%2Fcodespatter.com%2F2007%2F05%2F04%2Fserver-attack%2F';
  addthis_title  = 'Server+ATTACK';
  addthis_pub    = 'gallard';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12" ></script>


<p>Related posts:</p><ol><li><a href='http://codespatter.com/2009/04/23/how-to-speed-up-your-django-sites/' rel='bookmark' title='Permanent Link: How to Speed up Your Django Sites with NginX, Memcached, and django-compress'>How to Speed up Your Django Sites with NginX, Memcached, and django-compress</a> <small>A lot of these steps will speed up any kind...</small></li><li><a href='http://codespatter.com/2009/07/08/python-projects-in-users-home-directories-with-wsgi/' rel='bookmark' title='Permanent Link: Python Projects in Users&#8217; Home Directories with wsgi'>Python Projects in Users&#8217; Home Directories with wsgi</a> <small>Letting users put static files and php files in a...</small></li></ol>]]></content:encoded>
			<wfw:commentRss>http://codespatter.com/2007/05/04/server-attack/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
