<?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>Noemi Millman &#124; Triopter &#187; web dev</title>
	<atom:link href="http://triopter.com/archive/category/web-dev/feed/" rel="self" type="application/rss+xml" />
	<link>http://triopter.com</link>
	<description>Hello.  My name is Noemi Millman, and Triopter is my web development agency.  We handcraft beautiful, dynamic websites.</description>
	<lastBuildDate>Fri, 06 Aug 2010 16:32:23 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>On the Pitfalls of Overseas Outsourcing</title>
		<link>http://triopter.com/archive/on-the-pitfalls-of-overseas-outsourcing/</link>
		<comments>http://triopter.com/archive/on-the-pitfalls-of-overseas-outsourcing/#comments</comments>
		<pubDate>Fri, 06 Aug 2010 16:32:23 +0000</pubDate>
		<dc:creator>Noemi Millman</dc:creator>
				<category><![CDATA[freelancing]]></category>
		<category><![CDATA[outsourcing]]></category>
		<category><![CDATA[web dev]]></category>

		<guid isPermaLink="false">http://triopter.com/?p=193</guid>
		<description><![CDATA[Outsourcing overseas can be tempting, and there are times when it is an appropriate approach to a web project.  But it can be dangerous if you do not have the technical expertise to properly evaluate the quality of the work.  Let me tell you a little story:
Recently a client came to me with [...]]]></description>
			<content:encoded><![CDATA[<p>Outsourcing overseas can be tempting, and there are times when it is an appropriate approach to a web project.  But it can be dangerous if you do not have the technical expertise to properly evaluate the quality of the work.  Let me tell you a little story:</p>
<p>Recently a client came to me with a small project: a single new page on her site, password protected to keep out casual browsers and search engines, but not requiring a high degree of security.</p>
<p>When I&#8217;m very busy, as I am now, I occasionally subcontract to other American-based freelancers with whom I&#8217;ve worked closely and whom I trust to produce excellent work.  Because this project was in a language I rarely work in, I decided the most efficient use of the client&#8217;s money would be to subcontract to someone with more experience in that language.  I reached out to some contacts and was put in touch with someone who received enthusiastic recommendations.</p>
<p>Not realizing that this individual (who will remain nameless) actually ran an outsourcing firm, I sent him some instructions; the page was presented to me the next morning.</p>
<p>To someone not closely familiar with web technology, it might have looked perfect.  You input the password.  If it was incorrect, you received a warning and nothing happened.  If it was correct, you were redirected to the actual page.</p>
<p>However, there were two <strong>major</strong> flaws in the implementation that suggested that the requirements &#8212; or the reasoning behind them &#8212; had not been understood:</p>
<h3>1. Use of Javascript</h3>
<p>The password verification was implemented entirely in Javascript &#8212; I recognized this immediately from the alert box that appeared when an incorrect password was input.  The problem with this is that it is entirely client-side: i.e. performed in the user&#8217;s browser.  A user could simply &#8220;view source&#8221; for the page to retrieve both the password and the URL of the destination page.</p>
<h3>2. The destination page was not password protected</h3>
<p>That is, if you visited the URL of the destination page without first going through the password page, there was no validation performed &#8212; it could be accessed without a password.  This defeated both of the purposes of the password protection: the URL could be shared among users, and if a user were to put a link from another website to the page, it could be picked up by search engines.</p>
<p>I sent the project back to the subcontractor, explaining my disappointment with the use of client-side authentication.  He agreed to have the flaws corrected, and  it was at this point that I learned that he was outsourcing overseas.  </p>
<p>When the &#8220;corrected&#8221; page was returned to me the next morning, the password authentication had indeed been moved server-side (meaning that a casual user could not retrieve the password or destination URL); but the two-page structure that permitted unauthenticated access to the destination page had not been corrected (the correct behavior would have been to use a &#8220;cookie&#8221; to create a &#8220;session&#8221; identifying the user, and to refuse to present the destination page if the session did not indicate that the user had entered the password).</p>
<p>Finally, disappointed, I decided to implement the page myself, and will not charge the client for the time spent by the subcontractor.  Lesson learned: be certain in advance whether the subcontractor I&#8217;m hiring outsources.  I could have saved myself some time and money if I had known this &#8212; I might have hired someone else, or at the very least would have been much more specific in my instructions (overseas developers will typically implement whatever takes the least thought to meet the instructions given, so you must give them very explicit instructions.)</p>
<p>The same caveats apply to anyone hiring for web development.  If you are considering hiring an outsourcing company rather than an American-based agency or freelancer, be certain that you have someone in house with the technical savvy to both a) communicate very detailed instructions to the outsourcer, and b) evaluate the resulting product for technical flaws and adherence to specifications.</p>
<p>In the end, please consider hiring your friendly neighborhood freelancer, who will make the effort to understand the problem you are trying to solve; will be able to offer suggestions as to alternate and possibly more efficient solutions; and will consider it a point of pride to solve it <em>correctly</em>.</p>
]]></content:encoded>
			<wfw:commentRss>http://triopter.com/archive/on-the-pitfalls-of-overseas-outsourcing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introducing Usertrack: Drupal Module to Track User Login / Logout Status</title>
		<link>http://triopter.com/archive/introducing-usertrack-drupal-module-to-track-user-login-logout-status/</link>
		<comments>http://triopter.com/archive/introducing-usertrack-drupal-module-to-track-user-login-logout-status/#comments</comments>
		<pubDate>Thu, 17 Jun 2010 20:40:00 +0000</pubDate>
		<dc:creator>Noemi Millman</dc:creator>
				<category><![CDATA[Drupal]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[web dev]]></category>

		<guid isPermaLink="false">http://triopter.com/?p=189</guid>
		<description><![CDATA[As part of a recent project for the excellent Nolej Studios, I needed a way to track which Drupal users are currently logged in &#8212; this is surprisingly not really possible using the Drupal core, and even more surprisingly not supported by any contrib modules than I could identify.
The obvious solution was to code my [...]]]></description>
			<content:encoded><![CDATA[<p>As part of a recent project for the excellent Nolej Studios, I needed a way to track which Drupal users are currently logged in &#8212; this is surprisingly not really possible using the Drupal core, and even more surprisingly not supported by any contrib modules than I could identify.</p>
<p>The obvious solution was to code my own module, and here it is: <a href="http://triopter.com/wordpress/wp-content/uploads/2010/06/usertrack.zip">usertrack</a>.  You can also check it out from Subversion at <a href="http://svn.triopter.com/drupal/usertrack/trunk/usertrack/" target="_blank">http://svn.triopter.com/drupal/usertrack/trunk/usertrack/</a> .</p>
<p>Usertrack includes simple Views integration for filtering, sorting, and annotating your User view with login status and last logout date.  Please read the README for compatibility and installation notes.</p>
]]></content:encoded>
			<wfw:commentRss>http://triopter.com/archive/introducing-usertrack-drupal-module-to-track-user-login-logout-status/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Site Launch: Margaret Wolfson</title>
		<link>http://triopter.com/archive/site-launch-margaret-wolfson/</link>
		<comments>http://triopter.com/archive/site-launch-margaret-wolfson/#comments</comments>
		<pubDate>Tue, 09 Feb 2010 17:10:30 +0000</pubDate>
		<dc:creator>Noemi Millman</dc:creator>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[site launch]]></category>
		<category><![CDATA[web dev]]></category>

		<guid isPermaLink="false">http://triopter.com/?p=124</guid>
		<description><![CDATA[In Mid-January I launched a redesigned website for storyteller and creative professional Margaret Wolfson.  The site design was provided by the talented Irasema Rivera of Big I Ranch Design Studio.  
More info about the site.
]]></description>
			<content:encoded><![CDATA[<p>In Mid-January I launched a redesigned website for storyteller and creative professional <a href="http://www.margaretwolfson.com" target="_blank">Margaret Wolfson</a>.  The site design was provided by the talented Irasema Rivera of Big I Ranch Design Studio.  </p>
<p><a href="http://triopter.com/portfolio/margaret-wolfson/">More info about the site</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://triopter.com/archive/site-launch-margaret-wolfson/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NKMImageField 0.6 Wordpress Plugin: Updates and Bug Fixes!</title>
		<link>http://triopter.com/archive/nkmimagefield-0-6-wordpress-plugin-updates-and-bug-fixes/</link>
		<comments>http://triopter.com/archive/nkmimagefield-0-6-wordpress-plugin-updates-and-bug-fixes/#comments</comments>
		<pubDate>Wed, 16 Dec 2009 02:35:31 +0000</pubDate>
		<dc:creator>Noemi Millman</dc:creator>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[freebies]]></category>
		<category><![CDATA[nkmimagefield]]></category>
		<category><![CDATA[web dev]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://triopter.com/?p=90</guid>
		<description><![CDATA[I spent this evening working on my Wordpress plugin, NKMImageField, fixing most of the bugs mentioned in the previous comment thread.  The result is NKMImageField v0.6, which is now available for download from the Wordpress plugins site.
If you aren&#8217;t familiar with the plugin, it duplicates the image management dialogue to permit you to attach [...]]]></description>
			<content:encoded><![CDATA[<p>I spent this evening working on my Wordpress plugin, NKMImageField, fixing most of the bugs mentioned in the <a href="http://triopter.com/archive/announcing-nkmimagefield-a-custom-image-field-plugin-for-wordpress/">previous comment thread</a>.  The result is NKMImageField v0.6, which is now <a href="http://wordpress.org/extend/plugins/nkmimagefield/">available for download</a> from the Wordpress plugins site.</p>
<p>If you aren&#8217;t familiar with the plugin, it duplicates the image management dialogue to permit you to attach images to a post as metadata using a simple graphical interface &#8212; instead of having to locate, copy, and paste the URL into a custom field.</p>
<p>The new version allows fields to be accessed properly outside the Wordpress Loop as well as on archive and category pages.  It fixes several bugs including broken template tags and some data loss bugs that were related to post revisions, autosaves, and scheduled / future posts.  It&#8217;s been tested with Wordpress 2.8.6 and will likely still work with earlier versions going back to 2.7.</p>
<p>I&#8217;d like to extend a big thank you to everyone who submitted bug reports and fixes for the plugin &#8212; I hope you&#8217;ll <a href="http://triopter.com/contact/">contact me</a> so that I can give you credit (name and URL) in the documentation.</p>
]]></content:encoded>
			<wfw:commentRss>http://triopter.com/archive/nkmimagefield-0-6-wordpress-plugin-updates-and-bug-fixes/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Project Launch: Ad Council / Small Step Kids / Where the Wild Things Are</title>
		<link>http://triopter.com/archive/project-launch-ad-council-small-step-kids-where-the-wild-things-are/</link>
		<comments>http://triopter.com/archive/project-launch-ad-council-small-step-kids-where-the-wild-things-are/#comments</comments>
		<pubDate>Wed, 09 Sep 2009 19:31:00 +0000</pubDate>
		<dc:creator>Noemi Millman</dc:creator>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[freelancing]]></category>
		<category><![CDATA[web dev]]></category>

		<guid isPermaLink="false">http://triopter.com/?p=76</guid>
		<description><![CDATA[I recently launched a new campaign on the Ad Council&#8217;s Small Step Kids website &#8212; a joint campaign with the new Where the Wild Things Are movie.  This project was my second with the Ad Council, and involved incorporating new elements into an existing design as well as some really fun custom design work, [...]]]></description>
			<content:encoded><![CDATA[<p>I recently launched a new campaign on the Ad Council&#8217;s Small Step Kids website &#8212; a joint campaign with the new Where the Wild Things Are movie.  This project was my second with the Ad Council, and involved incorporating new elements into an existing design as well as some really fun custom design work, and I was pleased to see it go live.  See some <a href="http://triopter.com/portfolio/ad-council-small-step-kids-where-the-wild-things-are/">project details</a> in my portfolio, or <a target="_blank" href="http://smallstep.gov/kids/flash/index.html">the live site</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://triopter.com/archive/project-launch-ad-council-small-step-kids-where-the-wild-things-are/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django 1.0: Filtering object list and ForeignKey (ModelChoiceField) in Admin Site (contrib.admin)</title>
		<link>http://triopter.com/archive/django-10-filtering-object-list-and-foreignkey-modelchoicefield-in-admin-site-contribadmin/</link>
		<comments>http://triopter.com/archive/django-10-filtering-object-list-and-foreignkey-modelchoicefield-in-admin-site-contribadmin/#comments</comments>
		<pubDate>Fri, 15 May 2009 01:05:29 +0000</pubDate>
		<dc:creator>Noemi Millman</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[web dev]]></category>

		<guid isPermaLink="false">http://triopter.com/archive/django-10-filtering-object-list-and-foreignkey-modelchoicefield-in-admin-site-contribadmin/</guid>
		<description><![CDATA[I&#8217;m currently building a custom multi-blogging application in Django, and one of the challenges I ran into when developing the admin section was how to restrict users to seeing and editing only their own data.
Imagine the following (simplified) models:

class Blog(models.Model):
	&#160;	owner = models.OneToOneField(User, primary_key=True)
	&#160;	title = models.CharField(max_length=32)


class Entry(models.Model):
	&#160;	blog = models.ForeignKey(Blog)
	&#160;	slug = models.SlugField(max_length=255, db_index=True)
	&#160;	headline = models.CharField(max_length=255)
	&#160;	content = models.TextField()

If [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m currently building a custom multi-blogging application in Django, and one of the challenges I ran into when developing the admin section was how to restrict users to seeing and editing only their own data.</p>
<p>Imagine the following (simplified) models:<br />
<code><br />
class Blog(models.Model):<br />
	&nbsp;	owner = models.OneToOneField(User, primary_key=True)<br />
	&nbsp;	title = models.CharField(max_length=32)<br />
</code><br />
<code><br />
class Entry(models.Model):<br />
	&nbsp;	blog = models.ForeignKey(Blog)<br />
	&nbsp;	slug = models.SlugField(max_length=255, db_index=True)<br />
	&nbsp;	headline = models.CharField(max_length=255)<br />
	&nbsp;	content = models.TextField()<br />
</code></p>
<p>If I want to show the user only their own entries in the admin object list, I can filter the list in the <code>ModelAdmin.queryset</code> method &#8212; simple as pie:<br />
<code><br />
class EntryAdmin(admin.ModelAdmin):<br />
	&nbsp;	def queryset(self, request):<br />
	&nbsp;		&nbsp;	qs = super(EntryAdmin,self).queryset(request)<br />
	&nbsp;		&nbsp;	return qs.filter(blog__owner=request.user)<br />
</code></p>
<p>Now, say I want to also limit what blogs the user can assign the entry to.  There&#8217;s a useful little ModelAdmin method called <code>formfield_for_dbfield</code>, but it doesn&#8217;t receive the request as an argument.  What to do?</p>
<p>Well, the <code>ModelAdmin.get_form</code> method <em>does</em> receive the request as an argument, and it gets called before <code>formfield_for_dbfield</code>.  So let&#8217;s just put the request object somewhere that we can get to it later:<br />
<code><br />
class EntryAdmin(admin.ModelAdmin):<br />
	&nbsp;	def get_form(self, request, obj=None):<br />
	&nbsp;	self.request = request<br />
	&nbsp;	f = super(EntryAdmin,self).get_form(request, obj)<br />
	&nbsp;	return f<br />
</code></p>
<p>Then when we call <code>formfield_for_dbfield</code> we have easy access to the request:</p>
<p><code><br />
class EntryAdmin(admin.ModelAdmin):<br />
	&nbsp;	def formfield_for_dbfield(self, dbfield, **kwargs):<br />
	&nbsp;		&nbsp;	if dbfield.name == 'blog':<br />
	&nbsp;		&nbsp;		&nbsp;	kwargs['queryset'] = Blog.objects.filter(owner=self.request.user)<br />
	&nbsp;		&nbsp;	return super(EntryAdmin, self).formfield_for_dbfield(dbfield, **kwargs)<br />
</code></p>
<p>Not the world&#8217;s most elegant solution, but simple and effective.  And there&#8217;s plenty more you can do with these techniques.  Gotta love Django!</p>
]]></content:encoded>
			<wfw:commentRss>http://triopter.com/archive/django-10-filtering-object-list-and-foreignkey-modelchoicefield-in-admin-site-contribadmin/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Installing Payflow Pro on Mac OS X</title>
		<link>http://triopter.com/archive/installing-payflow-pro-on-mac-os-x/</link>
		<comments>http://triopter.com/archive/installing-payflow-pro-on-mac-os-x/#comments</comments>
		<pubDate>Wed, 31 Jan 2007 01:44:03 +0000</pubDate>
		<dc:creator>Noemi Millman</dc:creator>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[os x]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[web dev]]></category>

		<guid isPermaLink="false">http://triopter.com/archive/installing-payflow-pro-on-mac-os-x/</guid>
		<description><![CDATA[If you&#8217;ve done more than a little web development, you&#8217;ve probably encountered Payflow Pro, PayPal&#8217;s (previously Verisign&#8217;s) credit card processing solution.
It&#8217;s not supported on OS X.
But OS X is UNIX-y!  There&#8217;s a version for Linux!  Why won&#8217;t it work on OS X?  Can&#8217;t you google for installation instructions?
Well, no.  Perhaps my [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve done more than a little web development, you&#8217;ve probably encountered Payflow Pro, PayPal&#8217;s (previously Verisign&#8217;s) credit card processing solution.</p>
<p>It&#8217;s not supported on OS X.</p>
<p>But OS X is UNIX-y!  There&#8217;s a version for Linux!  Why won&#8217;t it work on OS X?  Can&#8217;t you google for installation instructions?</p>
<p>Well, no.  Perhaps my google-fu is weak, but I could find no information whatsoever about how to get it working.</p>
<p>In fact, if these guys hadn&#8217;t <a href="http://blog.duncandavidson.com/2005/05/ruby_java_and_p.html">pointed out</a> that <a href="http://www.clarkware.com/cgi/blosxom/2005/05/17#PayflowPro">it was possible</a>, I would have given up then and there.</p>
<p>But I got it installed.  And you can, too.  Here&#8217;s how:</p>
<ol>
<li>Make sure you have the Apple Developer Tools installed.</li>
<li>Download the Payflow Pro Java SDK (you have to log into a Payflow Pro account to get the download), and unzip it to your hard drive (it doesn&#8217;t matter where, as long as it&#8217;s a place where the user your web server runs as can get to it).</li>
<li><code>cd</code> into the <code>java</code> directory.</li>
<li>Set your paths.  I had trouble getting these to stick, so I&#8217;d love any suggestions anyone might have on that aspect:
<p><code>$ CLASSPATH=${CLASSPATH:-}:Verisign.jar:.;export CLASSPATH</code></p>
<p><code>$ libpath=.:../jni:../lib</code></p>
<p><code>$ LD_LIBRARY_PATH=$libpath:${LD_LIBRARY_PATH:-};export LD_LIBRARY_PATH</code></li>
<li>Compile the java code:
<p><code>$ javac PFProJava.java</code></li>
<li>Run a test transaction:
<p><code>$ java PFProJava test-payflow.verisign.com 443 "USER=YourUserName&#038;VENDOR=YourVendorName&#038;PARTNER=YourPartnerName&#038;PWD=YourPassword&#038;TRXTYPE=S&#038;TENDER=C&#038;ACCT=5105105105105100&#038;EXPDATE=1209&#038;AMT=1.23&#038;ZIP=12345&#038;comment1=Test JNI Transactions" 30</code></p>
<p>Don&#8217;t forget to insert the correct user/vendor/partner/password.</p>
<p>Oh, and when I tried it with an account that didn&#8217;t have a username (which is possible in payflow pro), it wouldn&#8217;t accept the transaction until I set the <code>USER</code> to be the same as the <code>VENDOR</code>.</li>
<li>I ran into another problem, which was that I kept getting a  <code>NoClassDefFoundError</code> even after following the above steps.  I fixed this by adding the absolute path to <code>Verisign.jar</code> to my CLASSPATH:
<p><code>$ CLASSPATH=${CLASSPATH:-}:/path/to/directory/Verisign.jar:.;export CLASSPATH</code></li>
<li>As I mentioned, I had a lot of trouble getting the CLASPATH to stick.  I couldn&#8217;t even run the binary from another directory &#8211; even if I speicified the full path to it.  In the end, the following sequence was the most reliable means of running a successful transaction:
<p><code>$ cd /path/to/binary/</code></p>
<p><code>$ CLASSPATH=${CLASSPATH:-}:Verisign.jar:/path/to/directory/Verisign.jar:.;export CLASSPATH</code></p>
<p><code>$ java PFProJava test-payflow.verisign.com 443 "USER=YourUserName&#038;VENDOR=YourVendorName&#038;PARTNER=YourPartnerName&#038;PWD=YourPassword&#038;TRXTYPE=S&#038;TENDER=C&#038;ACCT=5105105105105100&#038;EXPDATE=1209&#038;AMT=1.23&#038;ZIP=12345&#038;comment1=Test JNI Transactions" 30</code></p>
<p>Again, I&#8217;d gladly welcome suggestions as to how to make this work more fluidly.</li>
</ol>
<p>That&#8217;s that.  You&#8217;ve got it installed.  The following code will suffice to call it from PHP:</p>
<p><code>$pfpro_path = '/path/to/directory';</code></p>
<p><code>$pfpro_server = 'test-payflow.verisign.com'; // for test transactions.  Change this for live transactions.</code></p>
<p><code>$vars = '?your=values&#038;to=submit&#038;to=verisign'; // build this string appropriately from your variables according to the payflow documentation, and don't forget to run escapeshellcmd() on each one, since we'll be passing this to exec().</code></p>
<p><code>$cmd = 'cd "' . $pfpro_path . '; "; CLASSPATH=${CLASSPATH:-}:"' . $pfpro_path . '}Verisign.jar":.; export CLASSPATH; cd "' . $pfpro_path . '"; java PFProJava ' . $pfpro_server . ' 443 "' . $vars . '"'</code></p>
<p><code>$result_code = exec($cmd, $result_string);</code></p>
<p>Phew!</p>
<p>Good luck&#8230;. and if you happen to figure out that whole path issue, drop me a line!</p>
]]></content:encoded>
			<wfw:commentRss>http://triopter.com/archive/installing-payflow-pro-on-mac-os-x/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Adventures in Django &#8211; Comments and more</title>
		<link>http://triopter.com/archive/adventures-in-django-comments-and-more/</link>
		<comments>http://triopter.com/archive/adventures-in-django-comments-and-more/#comments</comments>
		<pubDate>Wed, 20 Dec 2006 22:00:02 +0000</pubDate>
		<dc:creator>Noemi Millman</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[web dev]]></category>

		<guid isPermaLink="false">http://triopter.com/archive/adventures-in-django-comments-and-more/</guid>
		<description><![CDATA[I was home sick from work today, so once I felt well enough to crawl out of bed and sit in front of the computer, I decided to catch up a bit more on my Django.
Quick-n-Easy Comments
First thing I did was to replace the commenting system I&#8217;d created for my blog-app-in-progress with the commenting framework [...]]]></description>
			<content:encoded><![CDATA[<p>I was home sick from work today, so once I felt well enough to crawl out of bed and sit in front of the computer, I decided to catch up a bit more on my Django.</p>
<h2>Quick-n-Easy Comments</h2>
<p>First thing I did was to replace the commenting system I&#8217;d created for my blog-app-in-progress with the <a href="http://code.djangoproject.com/wiki/UsingFreeComment">commenting framework</a> that comes for &#8220;free&#8221; with Django.Â  It&#8217;s not as fully featured as I might like, but it&#8217;s got some pretty nifty options, and is fairly easy to set up.Â  I figured I&#8217;d rather know how to use this than re-implement comments any time I want to add them to an app.</p>
<p>There are some interesting ways to <a href="http://www.b-list.org/weblog/2006/07/16/django-tips-hacking-freecomment">extend the functionality of Django&#8217;s comment framework</a>, although I don&#8217;t really like that they require editing the original source of that framework &#8212; especially since Django itself is likely to require upgrading frequently in the near future as we approach v.1.0.Â  Hopefully either the comments framework will be expanded further, or the model inheritance branch of Django that I&#8217;ve heard rumors of will eventually make that much less of an issue.</p>
<h2>Absolute URLs</h2>
<p>One thing I discovered was that the comments framework requires that the get_absolute_url() method be defined for any class that takes comments, so I took this opportunity to replace all the paths in my app with get_absolute_url() calls.Â  Except for the paths in the date-based generic templates, since a date object doesn&#8217;t have an absolute URL method.</p>
<p>I ended up adding some more global variables to settings.py, and constructing all the URLs from those, including the ones in urls.py and in the get_absolute_url() methods.Â  This should make future changes to path structure much simpler.</p>
<h2>Templates</h2>
<p>Lastly, I wrapped everything in the blog in the base template (after troubleshooting a problem with context not passed from a custom view to a custom tag), added a template tag so I could include a date-based archive menu in the sidebar, and set up some very basic design elements in a stylesheet in the header, to visually separate the sidebars from the content (I think this will make development a bit more pleasant).</p>
<p>All in all, not bad for another 4 hours or so of work in an unfamiliar language and framework.Â  I&#8217;m very pleased with how easy it is to develop in Django, although I&#8217;m still extremely frustrated at times with documentation that fails badly to describe syntax (I&#8217;m not talking about Python syntax only, but also which optional function arguments should or shouldn&#8217;t be in a dict; or syntax for Django&#8217;s template language).</p>
<p>I&#8217;m also pleased that I&#8217;m feeling better.Â  I might even venture to add chicken soup back into my diet tonight!</p>
]]></content:encoded>
			<wfw:commentRss>http://triopter.com/archive/adventures-in-django-comments-and-more/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Deco-What?</title>
		<link>http://triopter.com/archive/deco-what/</link>
		<comments>http://triopter.com/archive/deco-what/#comments</comments>
		<pubDate>Sun, 19 Nov 2006 20:10:40 +0000</pubDate>
		<dc:creator>Noemi Millman</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[web dev]]></category>

		<guid isPermaLink="false">http://triopter.com/archive/deco-what/</guid>
		<description><![CDATA[I&#8217;ve said before that I&#8217;m only a moderately experienced programmer.Â  One of the things I&#8217;m enjoying about learning Django is that it&#8217;s challenging me to pick up new concepts without getting bogged down in the details of implementation.
Yesterday I ran across decorators.Â  I had no idea what a decorator is, how it works, or what [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve said before that I&#8217;m only a moderately experienced programmer.Â  One of the things I&#8217;m enjoying about learning Django is that it&#8217;s challenging me to pick up new concepts without getting bogged down in the details of implementation.<br />
Yesterday I ran across decorators.Â  I had no idea what a decorator is, how it works, or what it&#8217;s used for.Â  Wikipedia <a href="http://en.wikipedia.org/wiki/Decorator_pattern">offers an overview</a>, which at least explains the general purpose, but then someone tells me that <a href="http://wiki.python.org/moin/PythonDecorators#head-caec7706f329280ac2911365840a36436f9ba5ad">Python decorators are not the same thing</a>.Â  The top Google results <a href="http://soiland.no/software/decorator">fly way over my head</a>, and finally, I land on an <a href="http://www.daniweb.com/code/snippet368.html">example that makes sense</a>.</p>
<p>So, to my understanding, a decorator is a function that gets wrapped around a second function.Â  When the second function is called, the decorator is effectively called instead, and <em>it</em> calls the second.Â  I could be completely misled, but I&#8217;m going to run with that for now.Â  If I&#8217;m wrong, won&#8217;t someone please please please correct me?</p>
]]></content:encoded>
			<wfw:commentRss>http://triopter.com/archive/deco-what/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django pretty much rocks</title>
		<link>http://triopter.com/archive/django-pretty-much-rocks/</link>
		<comments>http://triopter.com/archive/django-pretty-much-rocks/#comments</comments>
		<pubDate>Sun, 29 Oct 2006 19:28:10 +0000</pubDate>
		<dc:creator>Noemi Millman</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[web dev]]></category>

		<guid isPermaLink="false">http://triopter.com/archive/django-pretty-much-rocks/</guid>
		<description><![CDATA[Well, I&#8217;ve built a basic blog application in Django, complete with comments (and comment moderation), categories, and date-based archives, that would actually be presentable on a public-facing website.  It took a total of about 8 hours, and I&#8217;m very impressed with the framework.
My previous praise of the documentation was a little premature.  The [...]]]></description>
			<content:encoded><![CDATA[<p>Well, I&#8217;ve built a basic blog application in Django, complete with comments (and comment moderation), categories, and date-based archives, that would actually be presentable on a public-facing website.  It took a total of about 8 hours, and I&#8217;m very impressed with the framework.</p>
<p>My previous praise of the documentation was a little premature.  The docs are a thousand times more approachable than RoR&#8217;s, and better categorized and stuff.  But they&#8217;re very lacking in descriptions of syntax, or real-world examples, and in a few cases are out of date.</p>
<p>I spent 2 hours trying to figure out how to get date-based generic views to work before realizing that the examples I was finding on Google (unfortunately there are none on the Django docs wiki) were all a year out of date, and the view had to be called completely differently.  And then it was only by chance that I finally managed to stumble across an up-to-date example of the correct way to call them.</p>
<p>Still, I feel like I sort of understand how the framework functions, which is more than I can say for RoR.  I&#8217;ll probably be sticking to this.  Once I sort out a few last questions, I&#8217;m going to need a more ambitious project to try!</p>
]]></content:encoded>
			<wfw:commentRss>http://triopter.com/archive/django-pretty-much-rocks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
