<?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>Thomas Brox R&#248;st &#187; Google App Engine</title>
	<atom:link href="http://thomas.broxrost.com/category/google-app-engine/feed/" rel="self" type="application/rss+xml" />
	<link>http://thomas.broxrost.com</link>
	<description></description>
	<lastBuildDate>Tue, 04 May 2010 13:55:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Porting legacy databases to Google App Engine</title>
		<link>http://thomas.broxrost.com/2008/06/15/porting-legacy-databases-to-google-app-engine/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed</link>
		<comments>http://thomas.broxrost.com/2008/06/15/porting-legacy-databases-to-google-app-engine/#comments</comments>
		<pubDate>Sun, 15 Jun 2008 16:27:10 +0000</pubDate>
		<dc:creator>Thomas Brox Røst</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Google App Engine]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://thomas.broxrost.com/?p=23</guid>
		<description><![CDATA[A reader posed the following question: &#8220;I&#8217;m trying to convert my django app to work with google app engine. This is preferred rather than spending $100/year extra for a site with ssh access, plus I love the appengine dashboard. Here is my issue: My current django app is fairly static. It pulls all its data [...]]]></description>
			<content:encoded><![CDATA[<p> A reader posed the following question:</p>
<blockquote><p>&#8220;I&#8217;m trying to convert my django app to work with google app engine.  This is preferred rather than spending $100/year extra for a site with ssh access, plus I love the appengine dashboard.</p>
<p>Here is my issue: My current django app is fairly static.  It pulls all its data from a mysql database containing ~6,000 rows.  This itself is built from a gadfly database, so it should be pretty easy to get these values into the datastore/gql. </p>
<p>How can I sync my database with appengine?&#8221;</p></blockquote>
<p>This is a highly relevant problem if you are porting an existing Django application to the Google App Engine. Luckily, the App Engine SDK includes a <a href="http://code.google.com/appengine/articles/bulkload.html" target="_blank">bulk data uploader tool</a> that does the job. Let&#8217;s work through an example where we use this tool to transfer data from an existing MySQL database onto a Django application running on Google App Engine.</p>
<p><strong>Case description:</strong> We have an inventory database that is currently stored in MySQL. This database is to be made available through a Django web application that allows visitors to review the inventory. The database is named &#8216;customerdb&#8217; and has a single table called &#8216;inventory&#8217;:&#8217;</p>
<pre class="brush: python">
mysql&gt; select * from inventory;
+----------+----------+
| name     | quantity |
+----------+----------+
| ham      |        2 |
| cheese   |        7 |
| macaroni |        1 |
+----------+----------+
3 rows in set (0.00 sec)
</pre>
<p><strong>Setup:</strong> We need an App Engine-ready Django application that provides us with the views and models we need to display our inventory. For this scenario we will name the application &#8216;upload-demo&#8217; and make it available on <a href="http://upload-demo.appspot.com">http://upload-demo.appspot.com</a>. My <a href="http://thomas.broxrost.com/2008/04/08/django-on-google-app-engine/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed">earlier</a> <a href="http://thomas.broxrost.com/2008/04/20/django-on-google-app-engine-templates-and-static-files/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed">tutorials</a> should provide you with what you need to build the basic application structure.</p>
<p>The full set of application files can be downloaded <a href='http://thomas.broxrost.com/wp-content/uploads/2008/06/upload-demo.zip'>here</a>. References to the application name and paths will have to be changed according to your system setup.</p>
<p>Once the fundamentals are in place you should add an inventory model that mirrors the table in our database:</p>
<pre class="brush: python">
# upload-demo/uploaddemo/main/models.py

from google.appengine.ext import db

class Inventory(db.Model):
    name = db.StringProperty()
    quantity = db.IntegerProperty()
</pre>
<p>We also need a view that displays the data:</p>
<pre class="brush: python">
# upload-demo/uploaddemo/main/views.py

from django.http import HttpResponse
from uploaddemo.main.models import Inventory

def main(request):
    result = &quot;&quot;
    items = Inventory.all()

    for item in items:
        result += &quot;%s: %i&lt;br/&gt;&quot; % (item.name, item.quantity)

    return HttpResponse(result)
</pre>
<p>Finally, your <em>urls.py</em> should point towards the view:</p>
<pre class="brush: python">
# upload-demo/uploaddemo/urls.py

from django.conf.urls.defaults import *

urlpatterns = patterns(&quot;&quot;,
    (r&quot;^$&quot;, &quot;uploaddemo.main.views.main&quot;),
)
</pre>
<p>The application directory structure should look exactly like this:</p>
<p><img src="http://thomas.broxrost.com/wp-content/uploads/2008/06/directory_structure.jpg" alt="Project directory structure" title="directory_structure" width="304" height="218" class="alignnone size-full wp-image-20" /></p>
<p>To verify that we are good to go, deploy the application to App Engine:</p>
<pre class="brush: bash">
[test@mybox ~]$ appcfg.py update upload-demo
</pre>
<p>You should see an empty page&mdash;which makes sense since we have no data yet.</p>
<p><strong>Step 1 &#8211; Create a bulk load handler:</strong> The bulk loader accepts CSV-formatted data which it will feed it into the datastore:</p>
<pre class="brush: python">
# upload-demo/loader.py

from google.appengine.ext import bulkload

class InventoryLoader(bulkload.Loader):
    def __init__(self):
        fields = [
            (&quot;name&quot;, str),
            (&quot;quantity&quot;, int)
        ]

        bulkload.Loader.__init__(self, &quot;Inventory&quot;, fields)

if __name__ == &quot;__main__&quot;:
    bulkload.main(InventoryLoader())
</pre>
<p>In this case we have created a loader for the Inventory model where the fields match the name and type of the fields in the model. Note that the loader is kept outside of the Django application.</p>
<p><strong>Step 2 &#8211; Add the handler to the project:</strong> This is done by adding an entry to <em>app.yaml</em> that references <em>loader.py</em>:</p>
<pre class="brush: bash">
# upload-demo/app.yaml

application: upload-demo
version: 1
runtime: python
api_version: 1

handlers:
- url: /load
  script: loader.py
  login: admin
- url: /.*
  script: main.py
</pre>
<p>A login will be required to access the loader URL&mdash;we don&#8217;t want anyone to add to our inventory without permission.</p>
<p><strong>Step 3 &#8211; Convert the data to CSV:</strong></p>
<p>Getting this step right can be surprisingly tricky, depending on your legacy database. For MySQL you may have to make sure that the user account has file write access rights:</p>
<pre class="brush: bash">
[root@mybox ~]# mysql -u root
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 74740
Server version: 5.0.45 Source distribution

Type &#039;help;&#039; or &#039;\h&#039; for help. Type &#039;\c&#039; to clear the buffer.

mysql&gt; grant file on *.* to &#039;test&#039;@&#039;localhost&#039;;
Query OK, 0 rows affected (0.01 sec)

mysql&gt; flush privileges;
Query OK, 0 rows affected (0.01 sec)
</pre>
<p>This command might have to be run as root, depending on how your database is configured. To do the data dump we run the following <em>select</em> statement:</p>
<pre class="brush: bash">
[test@mybox ~]$ mysql -u test customerdb -e &quot;select * into
    outfile &#039;/tmp/inventory.txt&#039; fields terminated by &#039;,&#039; from
    inventory&quot;
[test@mybox ~]$ cat /tmp/inventory.txt
ham,2
cheese,7
macaroni,1
</pre>
<p>If you are using PostgreSQL you can achieve the same by using the <a href="http://www.postgresql.org/docs/8.3/static/sql-copy.html" target="_blank"><em>COPY</em></a> command.</p>
<p><strong>Step 4 &#8211; Upload the data:</strong> First, redeploy your application to App Engine:</p>
<pre class="brush: bash">
[test@mybox ~]$ appcfg.py update upload-demo
</pre>
<p>We then use the <em>bulkload_client.py</em> script to upload our CSV file. The script is found in the <em>tools</em> folder of your App Engine installation&mdash;you may have to add it to your PATH. Note that you have to use double dashes for the parameters.</p>
<pre class="brush: bash">
[test@mybox ~]$ bulkload_client.py --filename=/tmp/inventory.txt
    --kind=Inventory --url=http://upload-demo.appspot.com/load

INFO 2008-06-15 07:39:21,682 bulkload_client.py]
    Starting import; maximum 10 entities per post
INFO 2008-06-15 07:39:21,684 bulkload_client.py]
    Importing 3 entities in 29 bytes
ERROR 2008-06-15 07:39:21,997 bulkload_client.py]
    An error occurred while importing: Received code 302: Found
&lt;HTML&gt;&lt;HEAD&gt;&lt;meta http-equiv=&quot;content-type&quot; content=&quot;text/html;charset=utf-8&quot;&gt;
&lt;TITLE&gt;302 Moved&lt;/TITLE&gt;&lt;/HEAD&gt;&lt;BODY&gt;
&lt;H1&gt;302 Moved&lt;/H1&gt;
The document has moved
&lt;A HREF=&quot;https://www.google.com/accounts/ServiceLogin?service=ah&amp;
continue=http://upload-demo.appspot.com/_ah/login%3Fcontinue%3Dhttp://
upload-demo.appspot.com/load&amp;ltmpl=gm&amp;ahname=Django+data+u
pload+demo&amp;sig=f9861d41d527e55f15742b8d54504bcc&quot;&gt;here&lt;/A&gt;.
&lt;/BODY&gt;&lt;/HTML&gt;

ERROR    2008-06-15 07:39:21,997 bulkload_client.py] Import failed
</pre>
<p>Now, that didn&#8217;t work. Remember that <em>app.yaml</em> says we have to authenticate ourself as an admin user before we can upload data. Try visiting <a href="http://upload-demo.appspot.com/load" target="_blank">http://upload-demo.appspot.com/load</a> in a web browser. After having authenticated yourself using your Google account you will be redirected to the following page:</p>
<p><img src="http://thomas.broxrost.com/wp-content/uploads/2008/06/loader_authentication.jpg" alt="Loader authentication screen" title="loader_authentication" width="500" height="203" class="alignnone size-full wp-image-21" /></p>
<p>Just what we needed! Add the cookie string parameter to the previous request and try again:</p>
<pre class="brush: bash">
[test@mybox ~]$ bulkload_client.py --filename=/tmp/inventory.txt
    --kind=Inventory --url=http://upload-demo.appspot.com/load
    --cookie=&#039;ACSID=AJKiYcE[...]1Hh4&#039;

INFO 2008-06-15 07:50:58,541 bulkload_client.py]
    Starting import; maximum 10 entities per post
INFO 2008-06-15 07:50:58,549 bulkload_client.py]
    Importing 3 entities in 29 bytes
INFO 2008-06-15 07:50:59,102 bulkload_client.py]
    Import succcessful
</pre>
<p>If you visit <a href="http://upload-demo.appspot.com">http://upload-demo.appspot</a> you should now see the data we just uploaded.</p>
<p><strong>Final notes:</strong> This simple example should be enough to get you started. When converting real-life databases you will have to deal with more complex schemas with references between tables. The discussion <a href="http://groups.google.com/group/google-appengine/browse_thread/thread/f12c18d60c632dd3/271674e41ad2cdd6?#271674e41ad2cdd6" target="_blank">here</a> should point you in the right direction. You may also find the SDK documentation on <a href="http://code.google.com/appengine/docs/datastore/typesandpropertyclasses.html" target="_blank">types and property classes</a> useful when porting your legacy database.</p>
<div id="wherego_related"><h3>Readers who viewed this page, also viewed:</h3><ul><li><a href="http://thomas.broxrost.com/2009/05/27/on-the-sadness-of-nouns/" rel="bookmark" class="wherego_title">On the sadness of nouns</a></li><li><a href="http://thomas.broxrost.com/2010/02/02/aws-cuts-data-transfer-rates-pricing-comparison-update/" rel="bookmark" class="wherego_title">AWS cuts data transfer rates: Pricing comparison update</a></li><li><a href="http://thomas.broxrost.com/2009/08/28/updated-awsgo-daddy-dedicated-server-cost-comparison/" rel="bookmark" class="wherego_title">Updated AWS/Go Daddy dedicated server cost comparison</a></li><li><a href="http://thomas.broxrost.com/2008/04/08/django-on-google-app-engine/" rel="bookmark" class="wherego_title">Django on Google App Engine in 13 simple steps</a></li><li><a href="http://thomas.broxrost.com/2008/04/20/django-on-google-app-engine-templates-and-static-files/" rel="bookmark" class="wherego_title">Django on Google App Engine: Templates and static files</a></li><li>Powered by <a href="http://ajaydsouza.com/wordpress/plugins/where-did-they-go-from-here/">Where did they go from here?</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://thomas.broxrost.com/2008/06/15/porting-legacy-databases-to-google-app-engine/feed/</wfw:commentRss>
		<slash:comments>32</slash:comments>
		</item>
		<item>
		<title>Django on Google App Engine: Templates and static files</title>
		<link>http://thomas.broxrost.com/2008/04/20/django-on-google-app-engine-templates-and-static-files/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed</link>
		<comments>http://thomas.broxrost.com/2008/04/20/django-on-google-app-engine-templates-and-static-files/#comments</comments>
		<pubDate>Sun, 20 Apr 2008 14:21:30 +0000</pubDate>
		<dc:creator>Thomas Brox Røst</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Google App Engine]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://thomas.broxrost.com/?p=15</guid>
		<description><![CDATA[In a previous tutorial we learned how to set up a simple Django project on the Google App Engine. We also saw how to use the App Engine datastore in place of the Django model API. Now, let&#8217;s have a look at how to integrate Django templates. I will also show you how to serve [...]]]></description>
			<content:encoded><![CDATA[<p>In a <a href="http://thomas.broxrost.com/2008/04/08/django-on-google-app-engine/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed">previous tutorial</a> we learned how to set up a simple <a href="http://www.djangoproject.com/">Django</a> project on the <a href="http://code.google.com/appengine/">Google App Engine</a>. We also saw how to use the App Engine <a href="http://code.google.com/appengine/docs/datastore/">datastore</a> in place of the Django model API.</p>
<p>Now, let&#8217;s have a look at how to integrate Django templates. I will also show you how to serve static files.</p>
<p><strong>Important:</strong> Remember to <a href="http://code.google.com/p/googleappengine/downloads/list">upgrade to the latest version of the App Engine SDK</a> (version 1.0.1 at the time of writing). Otherwise, this tutorial will not work for you if you are developing on Windows.</p>
<p><strong>Step 1:</strong> Set up an App Engine project&mdash;I am calling mine <em>djangostatic</em>. Follow steps 1 through 7 from the <a href="http://thomas.broxrost.com/2008/04/08/django-on-google-app-engine/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed">previous tutorial</a>, remembering to substitute the project directory path and project name in <em>main.py</em> and <em>app.yaml</em>, and you will be all set.</p>
<p><strong>Step 2:</strong> We will create a simple view that makes use of a template. First, let us define the template. Create a directory where you can store templates:</p>
<pre class="brush: bash">
tmp/djangostatic$ cd djangostatic/main
tmp/djangostatic/djangostatic/main$ mkdir -p templates/main
</pre>
<p>Then, add the file <em>main.html</em > to your new template directory:</p>
<pre class="brush: html">
# djangostatic/djangostatic/main/templates/main/main.html

&lt;html&gt;
    &lt;head&gt;
        &lt;link href=&quot;/css/main.css&quot; type=&quot;text/css&quot;
               rel=&quot;stylesheet&quot;&gt;&lt;/link&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;p&gt;
            Hello world!
        &lt;/p&gt;
    &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Note that the template refers to a style sheet file, <em>main.css</em>, which we will create later on.</p>
<p><strong>Step 3:</strong> Django needs to be told where to search for template files: this is done in the <em>settings.py</em> file. The settings file is mostly pre-configured; we just have to modify the part that sets the <em>TEMPLATE_DIRS</em> variable:</p>
<pre class="brush: python">
# djangostatic/djangostatic/settings.py

import os
ROOT_PATH = os.path.dirname(__file__)

TEMPLATE_DIRS = (
    ROOT_PATH + &quot;/main/templates&quot;,
)
</pre>
<p><strong>Step 4:</strong> After creating the template and telling Django where to find it, we have to write a view that does the actual rendering:</p>
<pre class="brush: python">
# djangostatic/djangostatic/main/views.py

from django.shortcuts import render_to_response

def main(request):
    return render_to_response(&quot;main/main.html&quot;)
</pre>
<p>This tells Django to use the template <em>main/main.html</em> when rendering the response. The <em>render_to_response</em> method is a convenient shortcut for rendering a template and returning a response in one step.</p>
<p><strong>Step 5:</strong> Finally, we need to map a URL to our view&mdash;this is done in <em>urls.py</em>:</p>
<pre class="brush: python">
# djangostatic/djangostatic/urls.py

from django.conf.urls.defaults import *

urlpatterns = patterns(&quot;&quot;,
    (r&quot;^$&quot;, &quot;djangostatic.main.views.main&quot;),
)
</pre>
<p>Start your development server (<em>dev_appserver.py djangostatic</em>), fire up your browser, and open the page at <em>http://127.0.0.1:8080/</em>. If you have done everything right so far, you should get the &#8220;hello world&#8221; message from the template.</p>
<p><strong>Step 6:</strong> So what about the style sheet file, <em>main.css</em>? A style sheet file is a typical example of a static file. We use Django for rendering dynamic pages, so requests for static files should not be handled by the Django engine. In a regular Django application, we usually configure the web server to route such requests to a specific directory. On the App Engine, we achieve the same effect by adding a static handler to <em>app.yaml</em>:</p>
<pre class="brush: bash">
# djangostatic/app.yaml

application: djangostatic
version: 1
runtime: python
api_version: 1

handlers:
- url: /css
  static_dir: media/css

- url: /.*
  script: main.py
</pre>
<p>Here, we have added an entry that routes all requests beginning with <em>/css</em> to the directory <em>media/css</em>. Let us create this directory:</p>
<pre class="brush: bash">
tmp/djangostatic$ mkdir -p media/css
</pre>
<p><strong>Step 7:</strong> The link in our template specified <em>/css/main.css</em> as the full URL, so we have to add the <em>main.css</em> file to our new directory:</p>
<pre class="brush: css">
# djangostatic/media/css/main.css

p {
    font-size: 48px;
}
</pre>
<p>Reload the application page; the browser should now be able to make use of the style sheet so that the message is displayed in a larger font. You can view the final results <a href="http://djangostatic.appspot.com/">here</a>.</p>
<p><strong>Final notes:</strong> To learn more about how to serve static files on App Engine, have a look at the <a href="http://code.google.com/appengine/docs/configuringanapp.html">official documentation on how to configure an app</a>. Django templates are very powerful&mdash;this tutorial has only shown you the absolute basics. Visit the <a href="http://www.djangoproject.com/documentation/templates/">Django template documentation</a> to get the full story.</p>
<div id="wherego_related"><h3>Readers who viewed this page, also viewed:</h3><ul><li><a href="http://thomas.broxrost.com/2008/06/15/porting-legacy-databases-to-google-app-engine/" rel="bookmark" class="wherego_title">Porting legacy databases to Google App Engine</a></li><li><a href="http://thomas.broxrost.com/2009/08/28/updated-awsgo-daddy-dedicated-server-cost-comparison/" rel="bookmark" class="wherego_title">Updated AWS/Go Daddy dedicated server cost comparison</a></li><li><a href="http://thomas.broxrost.com/2009/03/12/why-amazon-web-services-just-became-a-competitive-web-hosting-provider/" rel="bookmark" class="wherego_title">Why Amazon Web Services just became a competitive web hosting provider</a></li><li><a href="http://thomas.broxrost.com/2008/04/08/django-on-google-app-engine/" rel="bookmark" class="wherego_title">Django on Google App Engine in 13 simple steps</a></li><li>Powered by <a href="http://ajaydsouza.com/wordpress/plugins/where-did-they-go-from-here/">Where did they go from here?</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://thomas.broxrost.com/2008/04/20/django-on-google-app-engine-templates-and-static-files/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Django on Google App Engine in 13 simple steps</title>
		<link>http://thomas.broxrost.com/2008/04/08/django-on-google-app-engine/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed</link>
		<comments>http://thomas.broxrost.com/2008/04/08/django-on-google-app-engine/#comments</comments>
		<pubDate>Tue, 08 Apr 2008 16:48:39 +0000</pubDate>
		<dc:creator>Thomas Brox Røst</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Google App Engine]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.broxrost.com/?p=8</guid>
		<description><![CDATA[In this tutorial I will show you how to get a simple datastore-backed Django application up and running on the Google App Engine. I will assume that you are somewhat familiar with Django. Update 1: You can download the full set of files from here. Make sure to fix the sys.path in main.py. Update 2: [...]]]></description>
			<content:encoded><![CDATA[<p>In this tutorial I will show you how to get a simple datastore-backed Django application up and running on the <a href="http://code.google.com/appengine/" target="_blank">Google App Engine</a>. I will assume that you are somewhat familiar with Django.</p>
<p><strong>Update 1:</strong> You can download the full set of files from <a href="http://thomas.broxrost.com/wp-content/uploads/2008/04/mashname.zip#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed">here</a>. Make sure to fix the sys.path in main.py.</p>
<p><strong>Update 2:</strong> There is now a <a href="http://www.tsdesign.info/blog/2008/04/11/google-app-engine-ile-13-basit-adimda-django/" target="_blank">Turkish translation</a> of this tutorial, courtesy of Türker Sezer.</p>
<p><strong>Update 3:</strong> Now in <a href="http://konkursof.blogspot.com/2008/05/django-google-app-engine-12.html" target="_blank">Russian</a> as well.</p>
<p><strong>Update 4:</strong> <a href="http://marcioandreyoliveira.blogspot.com/2009/04/13-passos-simples-para-termos-o-django.html">Brazilian Portuguese tranlation</a> by Marcio Andrey Oliveira.</p>
<hr /><strong>Step 1:</strong> Register an app name and install the development kit per the <a href="http://code.google.com/appengine/docs/gettingstarted/devenvironment.html" target="_blank">instructions</a>.</p>
<p><strong>Step 2:</strong> Create a directory for your application—for this tutorial my application is called <em>mashname</em>:</p>
<pre class="brush: bash">
tmp$ mkdir mashname
tmp$ cd mashname
</pre>
<p><strong>Step 3:</strong> Add a file called <em>main.py</em> to your new directory:</p>
<pre class="brush: python">
# main.py

import os, sys
os.environ[&amp;quot;DJANGO_SETTINGS_MODULE&amp;quot;] = &amp;quot;mashname.settings&amp;quot;
sys.path.append(&amp;quot;/home/brox/tmp/mashname&amp;quot;)

# Google App Engine imports.
from google.appengine.ext.webapp import util

# Force Django to reload its settings.
from django.conf import settings
settings._target = None

import django.core.handlers.wsgi
import django.core.signals
import django.db
import django.dispatch.dispatcher

# Log errors.
#django.dispatch.dispatcher.connect(
#   log_exception, django.core.signals.got_request_exception)

# Unregister the rollback event handler.
django.dispatch.dispatcher.disconnect(
django.db._rollback_on_exception,
django.core.signals.got_request_exception)

def main():
    # Create a Django application for WSGI.
    application = django.core.handlers.wsgi.WSGIHandler()

    # Run the WSGI CGI handler with that application.
    util.run_wsgi_app(application)

if __name__ == &amp;quot;__main__&amp;quot;:
    main()
</pre>
<p>This is basically the same file as suggested <a href="http://code.google.com/appengine/articles/django.html" target="_blank">here</a>, except I had to set the Python path to be able to test locally. I also had to set the DJANGO_SETTINGS_MODULE—this might not be necessary when running on the App Engine. I had to disable the error logging which I was not able to get working.</p>
<p><strong>Step 4:</strong> Add a file called <em>app.yaml</em> to the same directory:</p>
<pre class="brush: bash">
application: mashname
version: 1
runtime: python
api_version: 1

handlers:
- url: /.*
  script: main.py
</pre>
<p>Make sure to get the application name right.</p>
<p><strong>Step 5:</strong> From your <em>mashname</em> directory, create a new Django project:</p>
<pre class="brush: bash">
tmp/mashname$ django-admin.py startproject mashname
</pre>
<p>(I&#8217;m assuming that your current Django setup is working as it should.)</p>
<p><strong>Step 6:</strong> You should now be able to test your application:</p>
<pre class="brush: bash">
tmp/mashname$ cd ..
tmp$ dev_appserver.py mashname
INFO     2008-04-08 19:08:10,023 appcfg.py] Checking for updates to the SDK.
INFO     2008-04-08 19:08:10,384 appcfg.py] The SDK is up to date.
INFO     2008-04-08 19:08:10,404 dev_appserver_main.py] Running application mash
name on port 8080: http://localhost:8080
</pre>
<p>Point your browser towards <em>http://127.0.0.1:8080/</em> and you should get the standard Django <em>It worked!</em> message.</p>
<p><strong>Step 7:</strong> Create a Django app within the project:</p>
<pre class="brush: bash">
tmp$ cd mashname
tmp/mashname$ python mashname/manage.py startapp main
</pre>
<p><strong>Step 8:</strong> Now it is time to add a model. We will be creating a simple application that logs all visitors to the data store and displays their IP address and time of visit. Edit  <em>~/mashname/mashname/main/models.py</em> so that it looks like this:</p>
<pre class="brush: python">
# models.py

from google.appengine.ext import db

class Visitor(db.Model):
    ip = db.StringProperty()
    added_on = db.DateTimeProperty(auto_now_add=True)
</pre>
<p>There is no need to sync the database since we are not using regular Django models.</p>
<p><strong>Step 9:</strong> Now we create a view that is responsible for both adding data to the Visitor model and showing the previous visitors. Edit <em>views.py</em> (in the same directory as <em>models.py</em>) so that it does what we want:</p>
<pre class="brush: python">
# views.py

from django.http import HttpResponse

from mashname.main.models import Visitor

def main(request):
    visitor = Visitor()
    visitor.ip = request.META[&amp;quot;REMOTE_ADDR&amp;quot;]
    visitor.put()

    result = &amp;quot;&amp;quot;
    visitors = Visitor.all()
    visitors.order(&amp;quot;-added_on&amp;quot;)

    for visitor in visitors.fetch(limit=40):
        result += visitor.ip + u&amp;quot; visited on &amp;quot; + unicode(visitor.added_on) + u&amp;quot;&amp;quot;

    return HttpResponse(result)
</pre>
<p><strong>Step 10:</strong> Finally, make your <em>urls.py</em> point towards the view:</p>
<pre class="brush: python">
# urls.py

from django.conf.urls.defaults import *

urlpatterns = patterns(&amp;quot;&amp;quot;,
    (r&amp;quot;^$&amp;quot;, &amp;quot;mashname.main.views.main&amp;quot;),
)
</pre>
<p><strong>Step 11:</strong> Test your application (as in step 6) and everything should hopefully work. For each page reload a new entry is added to the Visitor model and shown in the view.</p>
<p><strong>Step 12:</strong> Upload your application to the Google App Engine:</p>
<pre class="brush: bash">
tmp$ appcfg.py update mashname
</pre>
<p>For the first upload you will have to provide the mail address and password for your Google account.</p>
<p><strong>Step 13:</strong> Enjoy! To view the final results, go to <a href="http://mashname.appspot.com/" target="_blank">http://mashname.appspot.com/</a>.</p>
<div id="wherego_related"><h3>Readers who viewed this page, also viewed:</h3><ul><li><a href="http://thomas.broxrost.com/2009/06/01/how-to-compile-simpleparse-210a1-for-python-26-on-windows-vista/" rel="bookmark" class="wherego_title">How to compile SimpleParse 2.1.0a1 for Python 2.6 on Windows Vista</a></li><li><a href="http://thomas.broxrost.com/2009/04/06/when-endnote-x2-fails/" rel="bookmark" class="wherego_title">When EndNote X2 fails</a></li><li><a href="http://thomas.broxrost.com/2008/04/20/django-on-google-app-engine-templates-and-static-files/" rel="bookmark" class="wherego_title">Django on Google App Engine: Templates and static files</a></li><li><a href="http://thomas.broxrost.com/2009/05/27/on-the-sadness-of-nouns/" rel="bookmark" class="wherego_title">On the sadness of nouns</a></li><li><a href="http://thomas.broxrost.com/2009/08/28/updated-awsgo-daddy-dedicated-server-cost-comparison/" rel="bookmark" class="wherego_title">Updated AWS/Go Daddy dedicated server cost comparison</a></li><li>Powered by <a href="http://ajaydsouza.com/wordpress/plugins/where-did-they-go-from-here/">Where did they go from here?</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://thomas.broxrost.com/2008/04/08/django-on-google-app-engine/feed/</wfw:commentRss>
		<slash:comments>51</slash:comments>
		</item>
	</channel>
</rss>
