<?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>kueda.net &#187; python</title>
	<atom:link href="http://kueda.net/blog/tag/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://kueda.net</link>
	<description>I'm Back</description>
	<lastBuildDate>Thu, 02 Feb 2012 19:42:04 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Using MySQL lat/lon Columns as a Mapnik Datasource</title>
		<link>http://kueda.net/blog/2009/05/04/mysql-as-mapnik-datasource/</link>
		<comments>http://kueda.net/blog/2009/05/04/mysql-as-mapnik-datasource/#comments</comments>
		<pubDate>Mon, 04 May 2009 05:07:28 +0000</pubDate>
		<dc:creator>Ken-ichi</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[google maps]]></category>
		<category><![CDATA[inaturalist]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[mapnik]]></category>
		<category><![CDATA[maps]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[ogr]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://kueda.net/?p=259</guid>
		<description><![CDATA[With the gracious help of Dane Springmeyer, I recently got Mapnik up and running on my Mac, so naturally the first thing I wanted to do was to plot iNaturalist observations. Mapnik will talk with a PostGIS database just fine, but it wont&#8217;t pull points from a MySQL database table, at least not directly. What [...]]]></description>
			<content:encoded><![CDATA[<p>With the gracious help of <a href="http://dbsgeo.com/" title="dbsgeo.com">Dane Springmeyer</a>, I recently got <a href="http://mapnik.org/" title="Mapnik C++/Python GIS Toolkit | Welcome">Mapnik</a> up and running on my Mac, so naturally the first thing I wanted to do was to plot <a href="http://inaturalist.org/" title="iNaturalist.org &middot; A Community for Naturalists">iNaturalist</a> observations.  Mapnik will talk with a PostGIS database just fine, but it wont&#8217;t pull points from a MySQL database table, at least not directly.  What it <em>does</em> support, though, is the all-powerful <a href="http://www.gdal.org/ogr/" title="OGR: OGR Simple Feature Library">OGR</a>.  Back when I used to use Mapserver, I had used OGR a few times to act as a bridge between simple lat/lon columns in a MySQL table and Mapserver (great description <a href="http://mapserver.org/input/vector/mysql.html" title="MySQL &mdash; MapServer 5.4.0 documentation">here</a>), so I figured the same would be possible in Mapnik.</p>
<p><span id="more-259"></span><br />
<h3>First Hurdle: Getting Mapnik to Show Anything At All</h3>
<p>First I made an OVF file so OGR would know how to talk to my database:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;OGRVRTDataSource<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;OGRVRTLayer</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;observations&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;SrcDataSource<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>MYSQL:inaturalist_development,user=root,tables=observations<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/SrcDataSource<span style="color: #000000; font-weight: bold;">&gt;</span></span></span> 
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;SrcSQL<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>SELECT id, latitude, longitude, iconic_taxon_id FROM observations<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/SrcSQL<span style="color: #000000; font-weight: bold;">&gt;</span></span></span> 
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;GeometryType<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>wkbPoint<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/GeometryType<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;GeometryField</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;PointFromColumns&quot;</span> <span style="color: #000066;">x</span>=<span style="color: #ff0000;">&quot;longitude&quot;</span> <span style="color: #000066;">y</span>=<span style="color: #ff0000;">&quot;latitude&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span> 
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/OGRVRTLayer<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/OGRVRTDataSource<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>and made sure it was working:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">mapnik-inat <span style="color: #000000; font-weight: bold;">&gt;</span> ogrinfo inat.ovf
ERROR <span style="color: #000000;">4</span>: Update access not supported <span style="color: #000000; font-weight: bold;">for</span> VRT datasources.
Had to open data <span style="color: #7a0874; font-weight: bold;">source</span> read-only.
INFO: Open of <span style="color: #000000; font-weight: bold;">`</span>inat.ovf<span style="color: #ff0000;">'
      using driver `VRT'</span> successful.
<span style="color: #000000;">1</span>: observations <span style="color: #7a0874; font-weight: bold;">&#40;</span>Point<span style="color: #7a0874; font-weight: bold;">&#41;</span></pre></div></div>

<p>Then I basically modified the Mapnik tutorial to use the OGR virtual data source:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> mapnik
&nbsp;
<span style="color: #808080; font-style: italic;"># Setup the datasource and layer</span>
ds = mapnik.<span style="color: black;">Ogr</span><span style="color: black;">&#40;</span><span style="color: #008000;">file</span>=<span style="color: #483d8b;">&quot;inat.ovf&quot;</span>, layer=<span style="color: #483d8b;">&quot;observations&quot;</span><span style="color: black;">&#41;</span>
lyr = mapnik.<span style="color: black;">Layer</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'test lyr'</span><span style="color: black;">&#41;</span>
lyr.<span style="color: black;">datasource</span> = ds
&nbsp;
<span style="color: #808080; font-style: italic;"># Style the points using a simple PNG</span>
m = mapnik.<span style="color: black;">Map</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">600</span>, <span style="color: #ff4500;">300</span>, <span style="color: #483d8b;">&quot;+proj=latlong +datum=WGS84&quot;</span><span style="color: black;">&#41;</span>
s = mapnik.<span style="color: black;">Style</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
r = mapnik.<span style="color: black;">Rule</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
symbolizer = mapnik.<span style="color: black;">PointSymbolizer</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'mm_8_stemless_iNatGreen.png'</span>, <span style="color: #483d8b;">'png'</span>, <span style="color: #ff4500;">8</span>, <span style="color: #ff4500;">8</span><span style="color: black;">&#41;</span>
symbolizer.<span style="color: black;">allow_overlap</span> = <span style="color: #008000;">True</span>
r.<span style="color: black;">symbols</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span>symbolizer<span style="color: black;">&#41;</span>
s.<span style="color: black;">rules</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span>r<span style="color: black;">&#41;</span>
m.<span style="color: black;">append_style</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'My Style'</span>, s<span style="color: black;">&#41;</span>
lyr.<span style="color: black;">styles</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'My Style'</span><span style="color: black;">&#41;</span>
m.<span style="color: black;">layers</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span>lyr<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Zoom to the extent of the data and write the map to a PNG</span>
m.<span style="color: black;">zoom_to_box</span><span style="color: black;">&#40;</span>lyr.<span style="color: black;">envelope</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
mapnik.<span style="color: black;">render_to_file</span><span style="color: black;">&#40;</span>m, <span style="color: #483d8b;">'test.png'</span>, <span style="color: #483d8b;">'png'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>And then I got a map!</p>
<p><img src="http://kueda.net/wp-content/uploads/2009/05/test.png" alt="test" title="test" width="600" height="300" class="aligncenter size-full wp-image-264" /></p>
<p>Ok, a kind of crappy map of test data, but actual, real, visible pixels!  So much better than arcane error messages!</p>
<h3>Second Hurdle: Google</h3>
<p>Of course, it&#8217;s just a map of some test points, but still, it worked.  Yay.  Next thing I wanted to do was to see how easy it would be to lay these points over a Google map, since one of the things I&#8217;d like to do with Mapnik is have a layer showing ALL observations on the iNat observation browser.  Turns out this was a piece of cake using <a href="http://bitbucket.org/springmeyer/tilelite/wiki/Home" title="springmeyer / TileLite / wiki / Home &mdash; bitbucket.org">tilelite</a>.</p>
<p>First I put my map configuration in an XML file, adding a bit of complexity using SQL filters to show different markers for different kinds of points (here corresponding to the IDs for different iconic taxa, e.g. plants, animals, fungi, etc.).</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Map</span> <span style="color: #000066;">srs</span>=<span style="color: #ff0000;">&quot;+proj=latlong +datum=WGS84&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Style</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;observationsStyle&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Rule<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Filter<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>[iconic_taxon_id] = 47126<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Filter<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;PointSymbolizer</span> <span style="color: #000066;">file</span>=<span style="color: #ff0000;">&quot;mm_8_stemless_iNatGreen.png&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;png&quot;</span> <span style="color: #000066;">width</span>=<span style="color: #ff0000;">&quot;8&quot;</span> <span style="color: #000066;">height</span>=<span style="color: #ff0000;">&quot;8&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Rule<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Rule<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Filter<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>[iconic_taxon_id] = 1 or [iconic_taxon_id] = 47178 or [iconic_taxon_id] = 3 or [iconic_taxon_id] = 20978 or [iconic_taxon_id] = 26036 or [iconic_taxon_id] = 40151<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Filter<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;PointSymbolizer</span> <span style="color: #000066;">file</span>=<span style="color: #ff0000;">&quot;mm_8_stemless_DodgerBlue.png&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;png&quot;</span> <span style="color: #000066;">width</span>=<span style="color: #ff0000;">&quot;8&quot;</span> <span style="color: #000066;">height</span>=<span style="color: #ff0000;">&quot;8&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Rule<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Rule<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Filter<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>[iconic_taxon_id] = 47115 or [iconic_taxon_id] = 47119 or [iconic_taxon_id] = 47158<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Filter<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;PointSymbolizer</span> <span style="color: #000066;">file</span>=<span style="color: #ff0000;">&quot;mm_8_stemless_OrangeRed.png&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;png&quot;</span> <span style="color: #000066;">width</span>=<span style="color: #ff0000;">&quot;8&quot;</span> <span style="color: #000066;">height</span>=<span style="color: #ff0000;">&quot;8&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Rule<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Rule<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Filter<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>[iconic_taxon_id] = 47170<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Filter<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;PointSymbolizer</span> <span style="color: #000066;">file</span>=<span style="color: #ff0000;">&quot;mm_8_stemless_DeepPink.png&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;png&quot;</span> <span style="color: #000066;">width</span>=<span style="color: #ff0000;">&quot;8&quot;</span> <span style="color: #000066;">height</span>=<span style="color: #ff0000;">&quot;8&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Rule<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Rule<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;ElseFilter</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;PointSymbolizer</span> <span style="color: #000066;">file</span>=<span style="color: #ff0000;">&quot;mm_8_stemless_unknown.png&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;png&quot;</span> <span style="color: #000066;">width</span>=<span style="color: #ff0000;">&quot;8&quot;</span> <span style="color: #000066;">height</span>=<span style="color: #ff0000;">&quot;8&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Rule<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Style<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Layer</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;observationsLayer&quot;</span> <span style="color: #000066;">srs</span>=<span style="color: #ff0000;">&quot;+proj=latlong +datum=WGS84&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;StyleName<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>observationsStyle<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/StyleName<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Datasource<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Parameter</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;type&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>ogr<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Parameter<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Parameter</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;file&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>inat.ovf<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Parameter<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Parameter</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;layer&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>observations<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Parameter<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Datasource<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Layer<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Map<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>Then I fired up tilelite:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">tilelite <span style="color: #000000; font-weight: bold;">&gt;</span> python liteserv.py ~<span style="color: #000000; font-weight: bold;">/</span>projects<span style="color: #000000; font-weight: bold;">/</span>mapnik-inat<span style="color: #000000; font-weight: bold;">/</span>inatmap.xml
Using mapfile: <span style="color: #ff0000;">'/Users/kueda/projects/mapnik-inat/inatmap.xml'</span>
Listening on port <span style="color: #000000;">8000</span>...</pre></div></div>

<p>and added a new GTileLayer to my map:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> myCopyright <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> GCopyrightCollection<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> allObsLyr <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> GTileLayer<span style="color: #009900;">&#40;</span>myCopyright<span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">12</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>
  isPNG<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
  tileUrlTemplate<span style="color: #339933;">:</span> <span style="color: #3366CC;">'http://localhost:8000/{Z}/{X}/{Y}.png'</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> allObsOverlay <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> GTileLayerOverlay<span style="color: #009900;">&#40;</span>allObsLyr<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
map.<span style="color: #660066;">addOverlay</span><span style="color: #009900;">&#40;</span>window.<span style="color: #660066;">allObsOverlay</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>et voila:</p>
<p><a href="http://kueda.net/wp-content/uploads/2009/05/picture-1.png"><img src="http://kueda.net/wp-content/uploads/2009/05/picture-1-300x236.png" alt="Mapnik-rendered observation points on an iNat map." title="Mapnik-rendered observation points on an iNat map." width="300" height="236" class="aligncenter size-medium wp-image-265" /></a></p>
<p>I have no idea how scalable this kind of solution is, but I just wanted to show that it works.  It was my first real experiment with Mapnik, and I&#8217;m pretty happy with how simple things were after the decidedly unsimple installation process.</p>
]]></content:encoded>
			<wfw:commentRss>http://kueda.net/blog/2009/05/04/mysql-as-mapnik-datasource/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Extending Existing Django ModelAdmin Classes</title>
		<link>http://kueda.net/blog/2008/07/25/extending-existing-django-modeladmin-classes/</link>
		<comments>http://kueda.net/blog/2008/07/25/extending-existing-django-modeladmin-classes/#comments</comments>
		<pubDate>Fri, 25 Jul 2008 19:04:39 +0000</pubDate>
		<dc:creator>Ken-ichi</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://kueda.net/?p=11</guid>
		<description><![CDATA[Django 1.0 is coming, and it&#8217;s bringing needed but backwards-incompatible changes to the admin site, ostensibly the best thing about Django.  One problem I&#8217;ve run into while migrating to the new version is inline editing of related classes in existing classes.  For example, it&#8217;s pretty common (and recommended) to &#8220;extend&#8221; Django&#8217;s built-in User model by [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://code.djangoproject.com/wiki/VersionOneRoadmap">Django 1.0 is coming</a>, and it&#8217;s bringing needed but backwards-incompatible changes to the admin site, ostensibly the best thing about Django.  One problem I&#8217;ve run into while migrating to the new version is inline editing of related classes in existing classes.  For example, it&#8217;s pretty common (and recommended) to &#8220;extend&#8221; Django&#8217;s built-in User model by creating your own, related Profile model.  For the old admin site, you specified the ability to edit a relate Profile in the User form in the Profile model:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Profile<span style="color: black;">&#40;</span>models.<span style="color: black;">Model</span><span style="color: black;">&#41;</span>:
    <span style="color: #dc143c;">user</span> = models.<span style="color: black;">ForeignKey</span><span style="color: black;">&#40;</span>User, unique=<span style="color: #008000;">True</span>, edit_inline=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span></pre></div></div>

<p>That was simple, but kinda quirky.  Changing the way the User form looks by changing the related Profile model?  Weird.  BUT, it did let you make changes to the User model w/o mucking with the built in Django code.</p>
<p>The new way of doing things is to specify all your admin site options in a separate file, and inline editing is now a little more reasonable: if you want to edit related objects in a model&#8217;s form, you specify that in that model&#8217;s admin options.  But this means you need to alter Django&#8217;s built-in User model&#8217;s admin options, which could mean muckiness.  So here&#8217;s what I did in my <code>myapp/admin.py</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">contrib</span> <span style="color: #ff7700;font-weight:bold;">import</span> admin
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">contrib</span>.<span style="color: black;">auth</span>.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> User
<span style="color: #ff7700;font-weight:bold;">from</span> myapp.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> ProfileAdmin<span style="color: black;">&#40;</span>admin.<span style="color: black;">ModelAdmin</span><span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># just some stuff for my profile forms</span>
    filter_horizontal = <span style="color: black;">&#40;</span><span style="color: #483d8b;">'teams'</span>,<span style="color: black;">&#41;</span>
    radio_fields = <span style="color: black;">&#123;</span><span style="color: #483d8b;">'appointment'</span>: admin.<span style="color: black;">HORIZONTAL</span><span style="color: black;">&#125;</span>
    list_display = <span style="color: black;">&#40;</span><span style="color: #483d8b;">'user'</span>, <span style="color: #483d8b;">'picture'</span>, <span style="color: #483d8b;">'appointment'</span>, <span style="color: #483d8b;">'affiliation'</span><span style="color: black;">&#41;</span>
admin.<span style="color: #dc143c;">site</span>.<span style="color: black;">register</span><span style="color: black;">&#40;</span>Profile, ProfileAdmin<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># need to make an inline class...  ick</span>
<span style="color: #ff7700;font-weight:bold;">class</span> ProfileInline<span style="color: black;">&#40;</span>admin.<span style="color: black;">StackedInline</span><span style="color: black;">&#41;</span>:
    model = Profile
    max_num = <span style="color: #ff4500;">1</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># the meat: grab the existing UserAdmin class, modify it, unregister User,</span>
<span style="color: #808080; font-style: italic;"># and re-register User with the modified UserAdmin</span>
UserAdmin = admin.<span style="color: #dc143c;">site</span>._registry<span style="color: black;">&#91;</span>User<span style="color: black;">&#93;</span>.__class__
UserAdmin.<span style="color: black;">inlines</span> = <span style="color: black;">&#91;</span>ProfileInline,<span style="color: black;">&#93;</span>
admin.<span style="color: #dc143c;">site</span>.<span style="color: black;">unregister</span><span style="color: black;">&#40;</span>User<span style="color: black;">&#41;</span>
admin.<span style="color: #dc143c;">site</span>.<span style="color: black;">register</span><span style="color: black;">&#40;</span>User, UserAdmin<span style="color: black;">&#41;</span></pre></div></div>

<p>Took me a while to realize admin.site._registry held <em>instances</em> of the ModelAdmin classes, not the classes themselves.  This technique also assumes that User gets registered with the admin site <em>before</em> you run this code.  I&#8217;m guessing the order in which <code>admin.autodiscover()</code> registers models is the same as the <code>INSTALLED_APPS</code> setting in <code>settings.py</code>.</p>
]]></content:encoded>
			<wfw:commentRss>http://kueda.net/blog/2008/07/25/extending-existing-django-modeladmin-classes/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

