<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="fr"><title>Geekeries dans la catégorie DjangoGeek</title><link href="http://pmarichal.net/geekeries/categories/djangogeek/" rel="alternate" /><id>http://pmarichal.net/geekeries/categories/djangogeek/</id><updated>2010-01-07T20:25:00+02:00</updated><subtitle>Les dernières geekeries dans la catégorie DjangoGeek</subtitle><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/GeekeriesCategorieDjangogeek" /><feedburner:info uri="geekeriescategoriedjangogeek" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry><title>

How to integrate Google Reader, Delicious.com and your blog using Django
</title><link href="http://feedproxy.google.com/~r/GeekeriesCategorieDjangogeek/~3/Izliifc08pM/" rel="alternate" /><updated>2010-01-07T20:25:00+02:00</updated><author><name>Philippe Marichal</name><email>philippe@pmarichal.net</email></author><id>http://pmarichal.net/geekeries/2010/01/07/how-integrate-google-reader-deliciouscom-and-your-/</id><summary type="html">

&lt;span style="font-style: italic"&gt;&lt;p&gt;I&amp;#8217;m a heavy user of Google Reader. I have more than 180 feeds in my listing. I&amp;#8217;m also a heavy user of &lt;a href="http://delicious.com"&gt;Delicious.com&lt;/a&gt;. I have &lt;a href="http://delicious.com/_Fil_"&gt;bookmarked&lt;/a&gt; more than 1900 &lt;span class="caps"&gt;URLS&lt;/span&gt; since October 2005. And I have a &lt;a href="/toile/"&gt;tumblelog&lt;/a&gt;. Now, if I had to take a site from one of my reading on Google Reader and manually save it on my site and then manually add it to Delicious, I would become nuts in less time to say the &lt;abbr title="Cheeseburger !"&gt;Magic Word&lt;/abbr&gt;. But here comes Django and some library at the&amp;nbsp;rescue.&lt;/p&gt;&lt;/span&gt;

&lt;p&gt;So, I need an automated mechanism that will able me to post from within Google Reader to my web site and then to add this to my Delicious account at the same time. Using Django and PyDelicious, it is really&amp;nbsp;easy.&lt;/p&gt;
&lt;h2&gt;The&amp;nbsp;model&lt;/h2&gt;
&lt;p&gt;First, we need a model in Django that will hold the various links in your database of&amp;nbsp;choice.&lt;/p&gt;
&lt;p&gt;Here is the (simplified) model for my tumblelog (source available &lt;a href="http://bitbucket.org/fil/links/"&gt;on bitbucket&lt;/a&gt;).&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="c"&gt;# models.py from the links application&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;A Link to a site (heavily geared towards delicious.com)&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;LIVE_STATUS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;L&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;DRAFT_STATUS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;D&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;STATUS_CHOICES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LIVE_STATUS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Live&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DRAFT_STATUS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Draft&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;URLField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;verify_exists&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;blank&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                    &lt;span class="n"&gt;help_text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Description on delicious.com&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;slug&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;blank&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;blank&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                    &lt;span class="n"&gt;help_text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;extended on delicious.com&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TagField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;posted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DateTimeField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;blank&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                        &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;help_text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;dt on delicious.com.Format is &lt;span class="caps"&gt;ISO8601&lt;/span&gt;: 1984-09-01T14:21:31Z&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;status&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;STATUS_CHOICES&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DRAFT_STATUS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;url&lt;/code&gt;, &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;, &lt;code&gt;tags&lt;/code&gt; and &lt;code&gt;posted&lt;/code&gt; fields are directly related to the various fields you can enter on Delicious.com (url, title, notes, tags and the posted date). I also have some meta fields like the &lt;code&gt;slug&lt;/code&gt; and the &lt;code&gt;status&lt;/code&gt; that handle some technicalities (more on that&amp;nbsp;later).&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;TagField&lt;/code&gt; comes directly from the quasi defacto standard django apps &lt;a href="http://code.google.com/p/django-tagging/"&gt;django-tagging&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Delicious&amp;nbsp;integration&lt;/h2&gt;
&lt;p&gt;The first step will be to make sure that each time I save a link, it is posted to my Delicious account. And thanks to the sleek &lt;a href="http://code.google.com/p/pydelicious/"&gt;pydelicious library&lt;/a&gt;, it is a breeze to do. Once you have download and install it, you should add the a &lt;code&gt;DELICIOUS_USER&lt;/code&gt; and a &lt;code&gt;DELICIOUS_PWD&lt;/code&gt; settings in your &lt;code&gt;settings.py&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Next import the delicious  &lt;span class="caps"&gt;API&lt;/span&gt; in your &lt;code&gt;models.py&lt;/code&gt; file.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pydelicious&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DeliciousAPI&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And overwrite the &lt;code&gt;save&lt;/code&gt; method in your &lt;code&gt;Link&lt;/code&gt; model.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="c"&gt;# models.py from the links application&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;posted_iso&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Return the posted date as an &lt;span class="caps"&gt;ISO8601&lt;/span&gt; date&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;iso&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;posted&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c"&gt;# replace the milliseconds by Z, to comply with delicious requirement&lt;/span&gt;
    &lt;span class="n"&gt;pos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;iso&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rfind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;pos&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iso&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;iso&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Z&amp;#39;&lt;/span&gt;
&lt;span class="n"&gt;posted_iso&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;span class="caps"&gt;ISO&lt;/span&gt; Format&amp;#39;&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LIVE_STATUS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;delicious&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DeliciousAPI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DELICIOUS_USER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DELICIOUS_PWD&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;delicious&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;posts_add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="n"&gt;extended&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;posted_iso&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                            &lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Nothing fancy here. Each time you save, first you call the &lt;code&gt;super().save&lt;/code&gt; method to let Django save your entry in the database. Then, before posting it to Delicious, you need to check if the status is &lt;code&gt;LIVE_STATUS&lt;/code&gt;. First, you don&amp;#8217;t want to save in Delicious a draft entry. And second, it will be very handy when we will post a link from within Google Reader. If the status is indeed &amp;#8216;live&amp;#8217;, then just instantiate a &lt;code&gt;DeliciousAPI&lt;/code&gt; object and call the &lt;code&gt;posts_add&lt;/code&gt; method with the various field as parameters. I did use the &lt;code&gt;replace=True&lt;/code&gt; argument to make sure I replace an existing &lt;span class="caps"&gt;URL&lt;/span&gt; in case I wanted to make, for instance, an update to the description later on (to fix typo and&amp;nbsp;whatnot).&lt;/p&gt;
&lt;p&gt;Notice that we also added a &lt;code&gt;posted_iso&lt;/code&gt; method to convert the &lt;code&gt;datetime&lt;/code&gt; field into proper &lt;span class="caps"&gt;ISO8601&lt;/span&gt; date string in order to comply with the Delicious&amp;nbsp;requirement.&lt;/p&gt;
&lt;h2&gt;Creating a custom &amp;#8216;send to&amp;#8217; in Google&amp;nbsp;Reader&lt;/h2&gt;
&lt;p&gt;Even if you don&amp;#8217;t have a web site, you can already use the &amp;#8216;send to&amp;#8217; feature of Google Reader to share links with other. Go to your Settings page and select the &amp;#8216;Send To&amp;#8217;&amp;nbsp;panel. &lt;/p&gt;
&lt;p&gt;&lt;img alt="Settings" src="http://media.pmarichal.net/geekeries/2010-01-07/gr-settings.png" /&gt;&lt;/p&gt;
&lt;p&gt;There, you can select the various integration already provided by Google (I have checked the Delicious, but you have quite a lot of pre-made&amp;nbsp;services). &lt;/p&gt;
&lt;p&gt;To create your own, simply click on the &amp;#8216;Create a custom link&amp;#8217; at the bottom and enter the various&amp;nbsp;information&lt;/p&gt;
&lt;p&gt;&lt;img alt="Create Custom Link" src="http://media.pmarichal.net/geekeries/2010-01-07/gr-createlink.png" /&gt;&lt;/p&gt;
&lt;p&gt;As show on the screenshot above, you have to provide a name, a &lt;span class="caps"&gt;URL&lt;/span&gt; and an optional icon &lt;span class="caps"&gt;URL&lt;/span&gt;. For the &lt;span class="caps"&gt;URL&lt;/span&gt;, Reader provides 4 handy substitutions: the source (which is the name of the blog or site), the title of the post, the url (of course) and even a short url (for Twitter and such). For our web site, the &lt;span class="caps"&gt;URL&lt;/span&gt; will look like this &lt;code&gt;http://yoursite.url/path/to/your/api/?title=${title}&amp;amp;url=${url}&lt;/code&gt;. Make sure to match the path with the one from your&amp;nbsp;URLConfs. &lt;/p&gt;
&lt;p&gt;Save it and now, when browsing Google Reader, you will have at the bottom of each post a &amp;#8216;send to&amp;#8217; menu with the various sharing&amp;nbsp;options.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Send to" src="http://media.pmarichal.net/geekeries/2010-01-07/gr-sendto.png" /&gt;&lt;/p&gt;
&lt;h2&gt;Adding an &lt;span class="caps"&gt;API&lt;/span&gt; on you&amp;nbsp;tumblelog&lt;/h2&gt;
&lt;p&gt;Finally, we need to hook this call from Google Reader with an &lt;span class="caps"&gt;API&lt;/span&gt; on your web site. It&amp;#8217;s very easy, thanks to Django. First, add an url pattern to your&amp;nbsp;URLConfs.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="c"&gt;# urls.py from the links application.&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;links.views&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;link_add&lt;/span&gt;

&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;patterns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="c"&gt;# ...&lt;/span&gt;
                   &lt;span class="c"&gt;# other stuff cut out for clarity&lt;/span&gt;
                   &lt;span class="c"&gt;# ...&lt;/span&gt;
                   &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;r&amp;#39;^api/add/$&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;login_required&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link_add&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;link_add&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                   &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Notice that this view is (very simply) protected from abuse with the &lt;code&gt;login_required&lt;/code&gt; decorator.&lt;/p&gt;
&lt;p&gt;Then add this view&amp;nbsp;method.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="c"&gt;# views.py from the links application&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;link_add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;&lt;span class="caps"&gt;GET&lt;/span&gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;url&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;&lt;span class="caps"&gt;GET&lt;/span&gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;title&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;link&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                &lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;slugify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Link&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DRAFT_STATUS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;HttpResponseRedirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urlresolvers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;admin:links_link_change&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,)))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;It simply extracts the url and title from the &lt;span class="caps"&gt;GET&lt;/span&gt; request coming from Google Reader, creates a Link object by setting the title and url from Google Reader, populating the slug from the title and setting the status to &lt;code&gt;Link.DRAFT_STATUS&lt;/code&gt;. Then the object is saved and the view redirect to the correct admin page, ready to be&amp;nbsp;reviewed.&lt;/p&gt;
&lt;p&gt;It is important to set the status to &lt;code&gt;DRAFT_STATUS&lt;/code&gt; as to prevent the &lt;code&gt;save&lt;/code&gt; method to post the link to Delicious without being reviewed and annotated via the admin&amp;nbsp;first.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;And there you have it. Browse your feed from within Google Reader. When you find something worthy, use the &amp;#8216;send to&amp;#8217; to post this to your web site. Review it in the awesome Django admin and save it to your Delicious account, all in a couple of&amp;nbsp;clicks.&lt;/p&gt;
&lt;p&gt;My next step will be to write a javascript bookmark link to automate this from site I find outside of Google Reader. But this will be for a &lt;a href="/geekeries/2010/02/09/javascript-bookmarklet/"&gt;future post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;
Posté le 7 janvier 2010 à 20h25 dans la catégorie DjangoGeek
.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/GeekeriesCategorieDjangogeek/~4/Izliifc08pM" height="1" width="1"/&gt;</summary><category term="DjangoGeek" /><feedburner:origLink>http://pmarichal.net/geekeries/2010/01/07/how-integrate-google-reader-deliciouscom-and-your-/</feedburner:origLink></entry><entry><title>

Liens du jour
</title><link href="http://feedproxy.google.com/~r/GeekeriesCategorieDjangogeek/~3/JqxbtHAZ8HY/" rel="alternate" /><updated>2009-12-09T23:30:00+02:00</updated><author><name>Philippe Marichal</name><email>philippe@pmarichal.net</email></author><id>http://pmarichal.net/geekeries/2009/12/09/liens-du-jour/</id><summary type="html">

&lt;span style="font-style: italic"&gt;&lt;p&gt;Liens du jour. Au menu: Django management commands, Go &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Python template&amp;nbsp;languages.&lt;/p&gt;&lt;/span&gt;

&lt;h2&gt;&lt;a href="http://blog.zacharyvoase.com/post/275566873" title="http://blog.zacharyvoase.com/post/275566873"&gt;Zachary Voase’s Blog — Fixing Django Management&amp;nbsp;Commands&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Truly excellent ideas to enhance the &lt;span class="caps"&gt;API&lt;/span&gt; of the management commands in&amp;nbsp;Django.&lt;/p&gt;
&lt;h2&gt;&lt;a href="http://research.swtch.com/" title="http://research.swtch.com/"&gt;research!rsc&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Excellent blog on different programming topics by Russ Cox, one of the Go developer. Be sure to check his Go&amp;nbsp;entries.&lt;/p&gt;
&lt;h2&gt;&lt;a href="http://compoundthinking.com/blog/index.php/2009/12/09/python-template-languages-part-1-django/" title="http://compoundthinking.com/blog/index.php/2009/12/09/python-template-languages-part-1-django/"&gt;Python Template languages (Part 1 — Django) | Compound&amp;nbsp;Thinking&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Reflection on all the different python templates. This time, Django templates, the pros and&amp;nbsp;cons.&lt;/p&gt;

&lt;p&gt;
Posté le 9 décembre 2009 à 23h30 dans les catégories ComputerGeek, DjangoGeek, PythonGeek
.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/GeekeriesCategorieDjangogeek/~4/JqxbtHAZ8HY" height="1" width="1"/&gt;</summary><category term="ComputerGeek" /><category term="DjangoGeek" /><category term="PythonGeek" /><feedburner:origLink>http://pmarichal.net/geekeries/2009/12/09/liens-du-jour/</feedburner:origLink></entry><entry><title>

Liens du jour
</title><link href="http://feedproxy.google.com/~r/GeekeriesCategorieDjangogeek/~3/8t3_h1I7oxU/" rel="alternate" /><updated>2009-12-07T12:15:00+02:00</updated><author><name>Philippe Marichal</name><email>philippe@pmarichal.net</email></author><id>http://pmarichal.net/geekeries/2009/12/07/liens-du-jour/</id><summary type="html">

&lt;span style="font-style: italic"&gt;&lt;p&gt;Les liens du jour. Comme ce week-end fût extrêmement chargé (c&amp;#8217;était la St Nicolas ici en Belgique), pas mal de retard dans les liens intéressants. Au menu du jour: Un remplaçant pour Trac, une release JQuery, les prises de courant anglaises et la photo en&amp;nbsp;2060.&lt;/p&gt;&lt;/span&gt;

&lt;h2&gt;&lt;a href="http://basieproject.org/" title="http://basieproject.org/"&gt;Basie&amp;nbsp;Project&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Basie project est un remplaçant de Trac, toujours écrit en python, mais en utilisant Django comme framework Web: sont inclus un wiki, du source management, du revision control, un issues tracker, des mailing lists même, etc&amp;nbsp;&amp;#8230;&lt;/p&gt;
&lt;h2&gt;&lt;a href="http://www.popphoto.com/Features/What-Photography-Will-Look-Like-By-2060" title="http://www.popphoto.com/Features/What-Photography-Will-Look-Like-By-2060"&gt;What Photography Will Look Like By&amp;nbsp;2060&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Un article intriguant et un peu effrayant (je me &amp;#8220;vieuxconnise&amp;#8221; de plus en plus) sur ce que sera la photo d&amp;#8217;ici 2060. Pure spéculation, mais s&amp;#8217;appuyant malgré tout sur quelques études&amp;nbsp;sérieuses.&lt;/p&gt;
&lt;h2&gt;&lt;a href="http://blog.jquery.com/2009/12/04/jquery-14-alpha-1-released/" title="http://blog.jquery.com/2009/12/04/jquery-14-alpha-1-released/"&gt;JQuery 1.4 alpha 1&amp;nbsp;released&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Une nouvelle release de l&amp;#8217;excellent framework Javascript JQuery. Le point intéressant de cette release est que, apparemment (comme la fait remarquer &lt;a href="http://simonwillison.net/2009/Dec/5/jquery/"&gt;Simon Willison&lt;/a&gt;, il n&amp;#8217;y a pas vraiment de nouvelles fonctionnalités, mais plutôt des améliorations sur les &lt;span class="caps"&gt;API&lt;/span&gt; existantes, sur les performances,&amp;nbsp;etc.&lt;/p&gt;
&lt;h2&gt;&lt;a href="http://www.iconeye.com/index.php?option=com_content&amp;amp;view=article&amp;amp;id=3864:rca-student-radically-improves-the-uk-plug" title="http://www.iconeye.com/index.php?option=com_content&amp;amp;view=article&amp;amp;id=3864:rca-student-radically-improves-the-uk-plug"&gt;&lt;span class="caps"&gt;RCA&lt;/span&gt; student radically improves the &lt;span class="caps"&gt;UK&lt;/span&gt;&amp;nbsp;plug&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Un étudiant du Royal College of Art a redesigné la prise de courant anglaise (une des plus moches au monde). Extrêmement&amp;nbsp;ingénieux.&lt;/p&gt;
&lt;p&gt;(Via &lt;a href="http://daringfireball.net/linked/2009/12/05/uk-plug"&gt;John Gruber&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;
Posté le 7 décembre 2009 à 12h15 dans les catégories ComputerGeek, DjangoGeek, PythonGeek, WebGeek
.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/GeekeriesCategorieDjangogeek/~4/8t3_h1I7oxU" height="1" width="1"/&gt;</summary><category term="ComputerGeek" /><category term="DjangoGeek" /><category term="PythonGeek" /><category term="WebGeek" /><feedburner:origLink>http://pmarichal.net/geekeries/2009/12/07/liens-du-jour/</feedburner:origLink></entry></feed>
