<?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>GrenadePod &#187; python</title>
	<atom:link href="http://www.grenadepod.com/tag/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.grenadepod.com</link>
	<description>Dispersing the Seeds</description>
	<lastBuildDate>Mon, 22 Feb 2010 20:30:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=abc</generator>
		<item>
		<title>Building python 2.6.4 RPM for CentOS 5.4</title>
		<link>http://www.grenadepod.com/2009/12/26/building-python-2-6-4-rpm-for-centos-5-4/</link>
		<comments>http://www.grenadepod.com/2009/12/26/building-python-2-6-4-rpm-for-centos-5-4/#comments</comments>
		<pubDate>Sat, 26 Dec 2009 10:37:25 +0000</pubDate>
		<dc:creator>pulegium</dc:creator>
				<category><![CDATA[IT Technology]]></category>
		<category><![CDATA[System administration]]></category>
		<category><![CDATA[CentOS]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.grenadepod.com/?p=655</guid>
		<description><![CDATA[CentOS is an enterprise linux distribution. And as such, it doesn&#8217;t really like anything new, unless it is a security patch. So it mostly contains older packages that are proven to be stable and secure. Any security patches and changes are backported to the older packages. This is all right for majority of the tools, [...]


Related posts:<ol><li><a href='http://www.grenadepod.com/2009/12/21/sorting-out-yum-repositories-on-centos-5-4/' rel='bookmark' title='Permanent Link: Sorting out YUM repositories on CentOS 5.4'>Sorting out YUM repositories on CentOS 5.4</a></li>
<li><a href='http://www.grenadepod.com/2009/11/23/use-ssh-to-upgrade-wordpress-plugins-automatically/' rel='bookmark' title='Permanent Link: Use SSH to upgrade WordPress plugins automatically'>Use SSH to upgrade WordPress plugins automatically</a></li>
<li><a href='http://www.grenadepod.com/2009/12/03/building-and-running-google-chrome-os-on-virtualbox/' rel='bookmark' title='Permanent Link: Building and running Google Chrome OS on VirtualBox'>Building and running Google Chrome OS on VirtualBox</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p id="top" />CentOS is an enterprise linux distribution. And as such, it doesn&#8217;t really like anything new, unless it is a security patch. So it mostly contains older packages that are proven to be stable and secure. Any security patches and changes are backported to the older packages. This is all right for majority of the tools, but some really needs upgrading. Python is a very good example. Python release, which is included in CentOS 5.4 is a rather old 2.4 branch. If you&#8217;re serious about python development, you really want to have 2.6. Unfortunately there is no CentOS RPM available. So here&#8217;s how to build your own.</p>
<p>First, you need to install RPM devtools:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;"># yum install rpmdevtools</pre></div></div>

<p>Then setup your local RPM build tree:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">$ rpmdev-setuptree</pre></div></div>

<p>This will create RPM build tree (~/rpmbuild/) in your home directory. Just a reminder &#8211; never, ever, under any circumstances, build RPMs as root user. Just a reminder. Obviously, you knew that already, right?</p>
<p>You also want to get and install additional header files and libraries, such as TCL/TK, expat, sqlite, etc, that are used to build some Python components:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;"># yum install tk-devel tcl-devel expat-devel db4-devel gdbm-devel sqlite-devel</pre></div></div>

<p>Now we&#8217;re ready to start building an RPM. Get the RPM spec file from source build tree and copy it to your rpmbuild/SPECS directory, also copy the tarball to your build directory:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">$ wget http://www.python.org/ftp/python/2.6.4/Python-2.6.4.tar.bz2
$ tar jxf Python-2.6.4.tar.bz2
$ cp Python-2.6.4/Misc/RPM/python-2.6.spec ~/rpmbuild/SPECS/
$ cp Python-2.6.4.tar.bz2 ~/rpmbuild/SOURCES/</pre></div></div>

<p>This spec file is slightly broken and if you try building an RPM with it, it most likely is going to fail. So you need to patch it. The <a href="http://bugs.python.org/issue5063" target="_blank">proposed patch</a> has been submitted to python bug tracking system in the days of 2.6.1 release, but hasn&#8217;t yet been implemented. This patch doesn&#8217;t seem to work with 2.6.4 release and needs changing as well.</p>
<p>I have modified original 2.6.1 patch file slightly so that it can be used to build 2.6.4 Python RPM. You <a href="http://www.grenadepod.com/wp-content/uploads/python-2.6.4.spec.diff">download it</a> and apply to the original .spec:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">$ cd ~/rpmbuild/SPECS/
$ wget http://www.grenadepod.com/wp-content/uploads/python-2.6.4.spec.diff
$ patch python-2.6.spec python-2.6.4.spec.diff</pre></div></div>

<p>You should be OK to build the RPM now, but it&#8217;ll most likely fail with minor rpath-check errors, such as:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">ERROR   0001: file '/usr/lib/python2.6/lib-dynload/_bsddb.so' contains a standard rpath '/usr/lib' in [/usr/lib]
ERROR   0001: file '/usr/lib/python2.6/lib-dynload/_sqlite3.so' contains a standard rpath '/usr/lib' in [/usr/lib]</pre></div></div>

<p>Which indicates that some components are using hardcoded library paths. It&#8217;s not a big issue and can be ignored. Run build command as this:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">$ QA_RPATHS=$[ 0x0001|0x0010 ] rpmbuild -ba python-2.6.spec</pre></div></div>

<p>It should now build without any issues and the result is a set of python RPMs:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">$ QA_RPATHS=$[ 0x0001|0x0010 ] rpmbuild -ba python-2.6.spec
...
Wrote: /home/pulegium/rpmbuild/SRPMS/python2.6-2.6.4-1gpod.src.rpm
Wrote: /home/pulegium/rpmbuild/RPMS/i386/python2.6-2.6.4-1gpod.i386.rpm
Wrote: /home/pulegium/rpmbuild/RPMS/i386/python2.6-devel-2.6.4-1gpod.i386.rpm
Wrote: /home/pulegium/rpmbuild/RPMS/i386/python2.6-tkinter-2.6.4-1gpod.i386.rpm
Wrote: /home/pulegium/rpmbuild/RPMS/i386/python2.6-tools-2.6.4-1gpod.i386.rpm
Wrote: /home/pulegium/rpmbuild/RPMS/i386/python2.6-debuginfo-2.6.4-1gpod.i386.rpm
...
$</pre></div></div>

<p>This is it&#8230; You now have python RPMs that you can install on your CentOS 5.x server.</p>
<p>I&#8217;m planning to create my little own repository, where I&#8217;ll put this (and other) packages. For now, you can download <a href="http://www.grenadepod.com/wp-content/uploads/python2.6-2.6.4-1gpod.src.rpm">python 2.6.4 source RPM</a> if you want to change something in the spec file and rebuild it yourself.</p>


<p>Related posts:<ol><li><a href='http://www.grenadepod.com/2009/12/21/sorting-out-yum-repositories-on-centos-5-4/' rel='bookmark' title='Permanent Link: Sorting out YUM repositories on CentOS 5.4'>Sorting out YUM repositories on CentOS 5.4</a></li>
<li><a href='http://www.grenadepod.com/2009/11/23/use-ssh-to-upgrade-wordpress-plugins-automatically/' rel='bookmark' title='Permanent Link: Use SSH to upgrade WordPress plugins automatically'>Use SSH to upgrade WordPress plugins automatically</a></li>
<li><a href='http://www.grenadepod.com/2009/12/03/building-and-running-google-chrome-os-on-virtualbox/' rel='bookmark' title='Permanent Link: Building and running Google Chrome OS on VirtualBox'>Building and running Google Chrome OS on VirtualBox</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.grenadepod.com/2009/12/26/building-python-2-6-4-rpm-for-centos-5-4/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Python web crawler</title>
		<link>http://www.grenadepod.com/2009/12/13/python-web-crawler/</link>
		<comments>http://www.grenadepod.com/2009/12/13/python-web-crawler/#comments</comments>
		<pubDate>Sun, 13 Dec 2009 20:57:51 +0000</pubDate>
		<dc:creator>pulegium</dc:creator>
				<category><![CDATA[IT Technology]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.grenadepod.com/?p=633</guid>
		<description><![CDATA[For one of my (upcoming) projects I needed to write a simple webcrawler. Just as I always do, I searched Google (obviously), but couldn&#8217;t find anything simple enough. Or good enough for me for that matter. So spent an hr or so writing most simplistic webcrawler myself. Application logic is extremely simple: Retrieve specified page [...]


Related posts:<ol><li><a href='http://www.grenadepod.com/2009/11/10/changing-menu-order/' rel='bookmark' title='Permanent Link: Changing menu order'>Changing menu order</a></li>
<li><a href='http://www.grenadepod.com/2009/11/04/top-level-menu-in-arras-theme/' rel='bookmark' title='Permanent Link: Top level menu in Arras theme'>Top level menu in Arras theme</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p id="top" />For one of my (upcoming) projects I needed to write a simple webcrawler. Just as I always do, I searched Google (obviously), but couldn&#8217;t find anything simple enough. Or good enough for me for that matter. So spent an hr or so writing most simplistic webcrawler myself.</p>
<p>Application logic is extremely simple:</p>
<ul>
<li>Retrieve specified page</li>
<li>If cannot retrieve, try another from stored in the DB</li>
<li>Store all found URLs (&lt;a href&gt;) in the DB</li>
<li>Return one (and remove from DB)</li>
</ul>
<p>I store all pages in memory, but for more serious crawling, consider storing data on a physical file, that way it&#8217;ll be more memory efficient. Considering the size of the internets, even if you store only URL strings you will not last for very long&#8230;</p>
<p>Anyway, happy crawling! (and let me know if there are any issues, so far it worked fine for me)</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> BeautifulSoup <span style="color: #ff7700;font-weight:bold;">import</span> BeautifulSoup
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">urllib2</span>, <span style="color: #dc143c;">random</span>, <span style="color: #dc143c;">re</span>, sqlite3, <span style="color: #dc143c;">logging</span>
&nbsp;
DATABASE   = <span style="color: #483d8b;">':memory:'</span>
LOG_LEVEL  = <span style="color: #dc143c;">logging</span>.<span style="color: black;">INFO</span>
ABS_URL_RE = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'(?P&lt;url&gt;https?://.+?/)'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> WebCrawler:
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, logging_level=LOG_LEVEL, database=DATABASE<span style="color: black;">&#41;</span>:
        <span style="color: #dc143c;">logging</span>.<span style="color: black;">basicConfig</span><span style="color: black;">&#40;</span>level=logging_level<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">conn</span> = sqlite3.<span style="color: black;">connect</span><span style="color: black;">&#40;</span>database<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">conn</span>.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'create table url_stack (url text)'</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">conn</span>.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'create table url_visited (url text)'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _form_url<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, url, link<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> link<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span>:<span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span> == <span style="color: #483d8b;">'http'</span>:
            ret_url = link
        <span style="color: #ff7700;font-weight:bold;">elif</span> link<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> == <span style="color: #483d8b;">'/'</span>:
            m = ABS_URL_RE.<span style="color: black;">search</span><span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>
            ret_url = <span style="color: #483d8b;">&quot;%s%s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>m.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'url'</span><span style="color: black;">&#41;</span>, link<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>:<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            ret_url = <span style="color: #483d8b;">&quot;%s%s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>url, link<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> ret_url
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _pop_from_db<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Retrieving one URL from the DB...&quot;</span><span style="color: black;">&#41;</span>
        res = <span style="color: #008000;">self</span>.<span style="color: black;">conn</span>.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'select url from url_stack limit 1'</span><span style="color: black;">&#41;</span>.<span style="color: black;">fetchone</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Query result: %s&quot;</span>, res<span style="color: black;">&#41;</span>
        url = res<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">conn</span>.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;delete from url_stack where url = ?&quot;</span>, <span style="color: black;">&#40;</span>url,<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> url
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _push_to_db<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, url<span style="color: black;">&#41;</span>:
        <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Inserting record into DB...&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Check if it hasn't been visited yet&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">self</span>.<span style="color: black;">conn</span>.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'select url from url_visited where url=?'</span>, <span style="color: black;">&#40;</span>url,<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>.<span style="color: black;">fetchone</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
            <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;URL not found in list of visited URLs, inserting&quot;</span><span style="color: black;">&#41;</span>
            <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;URL to insert: %s&quot;</span> <span style="color: #66cc66;">%</span> url<span style="color: black;">&#41;</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">conn</span>.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'insert into url_stack values (?)'</span>, <span style="color: black;">&#40;</span>url,<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">conn</span>.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'insert into url_visited values (?)'</span>, <span style="color: black;">&#40;</span>url,<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;URL has already been visited or added for processing, skipping&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> crawl<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, url<span style="color: black;">&#41;</span>:
        work_url = url
        <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Work URL: %s&quot;</span> <span style="color: #66cc66;">%</span> work_url<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
            <span style="color: #ff7700;font-weight:bold;">try</span>:
                <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Trying to open and parse the URL...&quot;</span><span style="color: black;">&#41;</span>
                page = <span style="color: #dc143c;">urllib2</span>.<span style="color: black;">urlopen</span><span style="color: black;">&#40;</span>work_url<span style="color: black;">&#41;</span>
                soup = BeautifulSoup<span style="color: black;">&#40;</span>page<span style="color: black;">&#41;</span>
                <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Parsed successfuly&quot;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">except</span>:
                <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Failed to parse, attempting to get next URL from DB&quot;</span><span style="color: black;">&#41;</span>
                work_url = <span style="color: #008000;">self</span>._pop_from_db<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
                <span style="color: #ff7700;font-weight:bold;">continue</span>
            links = soup<span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: black;">&#41;</span>
            <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Found total of %d links (&lt;a href=...&gt;)&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>links<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">for</span> link <span style="color: #ff7700;font-weight:bold;">in</span> soup<span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: black;">&#41;</span>:
                <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Processing link object: %s&quot;</span> <span style="color: #66cc66;">%</span> link<span style="color: black;">&#41;</span>
                <span style="color: #ff7700;font-weight:bold;">try</span>:
                    <span style="color: #ff7700;font-weight:bold;">if</span> link<span style="color: black;">&#91;</span><span style="color: #483d8b;">'href'</span><span style="color: black;">&#93;</span> <span style="color: #66cc66;">!</span>= <span style="color: #483d8b;">''</span>:
                        <span style="color: #008000;">self</span>._push_to_db<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>._form_url<span style="color: black;">&#40;</span>work_url, link<span style="color: black;">&#91;</span><span style="color: #483d8b;">'href'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
                <span style="color: #ff7700;font-weight:bold;">except</span>:
                    <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;An exception has occured, this may be ok (href attribute may be missing)&quot;</span><span style="color: black;">&#41;</span>
                    <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;  ... but can also indicate error in insert code&quot;</span><span style="color: black;">&#41;</span>
            <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Finished adding URLs&quot;</span><span style="color: black;">&#41;</span>
            <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Getting a new URL for processing from DB&quot;</span><span style="color: black;">&#41;</span>
            work_url = <span style="color: #008000;">self</span>._pop_from_db<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            <span style="color: #dc143c;">logging</span>.<span style="color: black;">info</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Found URL: %s&quot;</span> <span style="color: #66cc66;">%</span> work_url<span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">yield</span> work_url
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    wc = WebCrawler<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> url <span style="color: #ff7700;font-weight:bold;">in</span> wc.<span style="color: black;">crawl</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://www.google.com/'</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">pass</span></pre></td></tr></table></div>

<p>As you can see it&#8217;s very easy to use. Effectively it is an infinite generator (well, depending what you pass as initial URL). It&#8217;s then up to you what you&#8217;re going to do with the resulting URL&#8230;</p>
<p>One thing to bear in mind when you use it: this crawler pays absolutely no attention to the domain it&#8217;s searching. It just blindly collects links, selects one and follows it. So depending on the site link relative location it may stay for a while on a site, or may just wonder away quite quickly.</p>
<p>I wanted to have something that does not stick around for long on one site, so this suits me well, if you want to have something more pedantic, you may want to modify the code, so that it leaves current domain only when it has visited all pages and there are no new pages within the domain to analyse.</p>


<p>Related posts:<ol><li><a href='http://www.grenadepod.com/2009/11/10/changing-menu-order/' rel='bookmark' title='Permanent Link: Changing menu order'>Changing menu order</a></li>
<li><a href='http://www.grenadepod.com/2009/11/04/top-level-menu-in-arras-theme/' rel='bookmark' title='Permanent Link: Top level menu in Arras theme'>Top level menu in Arras theme</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.grenadepod.com/2009/12/13/python-web-crawler/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using OpenID for authentication in Django</title>
		<link>http://www.grenadepod.com/2009/11/22/using-openid-for-authentication-in-django/</link>
		<comments>http://www.grenadepod.com/2009/11/22/using-openid-for-authentication-in-django/#comments</comments>
		<pubDate>Sun, 22 Nov 2009 18:03:51 +0000</pubDate>
		<dc:creator>pulegium</dc:creator>
				<category><![CDATA[IT Technology]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[openid]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.grenadepod.com/?p=446</guid>
		<description><![CDATA[Tired of memorising login details for million different websites? Wanted to download or check somethning, but been prompted to created a user account on some random website? We&#8217;ve all been in this situation. And for me personally, I would steer away from the site that forces me to register just to see some part of [...]


Related posts:<ol><li><a href='http://www.grenadepod.com/2009/12/13/python-web-crawler/' rel='bookmark' title='Permanent Link: Python web crawler'>Python web crawler</a></li>
<li><a href='http://www.grenadepod.com/2009/11/09/how-to-use-generic-views-in-django/' rel='bookmark' title='Permanent Link: How to use generic views in Django'>How to use generic views in Django</a></li>
<li><a href='http://www.grenadepod.com/2009/12/03/building-and-running-google-chrome-os-on-virtualbox/' rel='bookmark' title='Permanent Link: Building and running Google Chrome OS on VirtualBox'>Building and running Google Chrome OS on VirtualBox</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p id="top" />Tired of memorising login details for million different websites? Wanted to download or check somethning, but been prompted to created a user account on some random website?</p>
<p>We&#8217;ve all been in this situation. And for me personally, I would steer away from the site that forces me to register just to see some part of forum or similar. Mostly this is because I don&#8217;t want to provide my details and follow lengthy registration process.</p>
<p>I don&#8217;t mind to have an account (even though I forget about the website next day), but the whole process of typing in all the stuff, deciphering captcha images, logging in to my email account just to confirm registration, etc, etc. Why don&#8217;t they use OpenId? These days if you have Yahoo or Gmail account (and just who doesn&#8217;t?) you can use them to login to all websites that support OpenId.</p>
<p>In a nutshell, OpenId is a decentralised authentication standard. User (U) who has an OpenId account with a trusted company (C) wants to login to a website (W). W prompts with a login screen. U enters his/her OpenId URL (no personal information here provided at all). W then redirects to C login screen, where U is prompted to allow access to some parts of the information (usually it&#8217;s username only, sometimes email). If U is happy to provide this information, he then clicks login button and information is passed back to W. In this scenario, W will never get any personal information about U without explicit permission. And U benefits from having only one login that works for all websites.</p>
<p>Below is a simple diagram that shows how authentication is done when using OpenId to login to the websites:</p>
<div id="attachment_476" class="wp-caption aligncenter" style="width: 476px"><img class="size-full wp-image-476" title="OID identification" src="http://www.grenadepod.com/wp-content/uploads/2009/11/OID-identification.jpg" alt="Authentication with OpenID flow" width="466" height="317" /><p class="wp-caption-text">Authentication with OpenID flow</p></div>
<p>Unfortunately Django does not have native support for OpenId, and their website recommends using <a href="http://bitbucket.org/benoitc/django-authopenid/wiki/Home" target="_blank">django-authopenid</a> library to perform authentication and login using OpenId.</p>
<h3>Install required libraries</h3>
<p>You need to install <a href="http://openidenabled.com/python-openid/" target="_blank">python-openid</a> library first. Installation is a breeze, however there seems to be some issues with internal version number in the package, but let&#8217;s assume it&#8217;s all fine:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;"># easy_install python-openid
Searching for python-openid
Reading http://pypi.python.org/simple/python-openid/
Reading http://openidenabled.com/python-openid/
Reading http://www.openidenabled.com/openid/libraries/python/
Best match: python-openid 2.2.4
Downloading http://openidenabled.com/files/python-openid/packages/python-openid-2.2.4.zip
Processing python-openid-2.2.4.zip
Running python-openid-2.2.4/setup.py -q bdist_egg --dist-dir /tmp/easy_install-Xyxx61/python-openid-2.2.4/egg-dist-tmp-oexXVf
zip_safe flag not set; analyzing archive contents...
Adding python-openid 2.2.4 to easy-install.pth file
&nbsp;
Installed /usr/lib/python2.5/site-packages/python_openid-2.2.4-py2.5.egg
Processing dependencies for python-openid
Finished processing dependencies for python-openid
# python
Python 2.5.1 (r251:54863, Jul 31 2008, 23:17:43)
[GCC 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)] on linux2
Type &quot;help&quot;, &quot;copyright&quot;, &quot;credits&quot; or &quot;license&quot; for more information.
&amp;gt;&amp;gt;&amp;gt; openid.__version__
'2.2.1'
&amp;gt;&amp;gt;&amp;gt; openid.__path__
['/usr/lib/python2.5/site-packages/python_openid-2.2.4-py2.5.egg/openid']
&amp;gt;&amp;gt;&amp;gt; openid.version_info
(2, 2, 1)
&amp;gt;&amp;gt;&amp;gt;</pre></div></div>

<p>Then install django-authopenid. Installation seems to spit out some errors, but I guess these can be ignored as they don&#8217;t seem to cause any issues:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;"># easy_install django-authopenid
Searching for django-authopenid
Reading http://pypi.python.org/simple/django-authopenid/
Reading http://hg.e-engura.org/django-authopenid/
Reading http://code.google.com/p/django-authopenid/
Best match: django-authopenid 1.0.1
Downloading http://pypi.python.org/packages/source/d/django-authopenid/django-authopenid-1.0.1.tar.gz#md5=93d44b4ce40de55bed36c9ed292adb49
Processing django-authopenid-1.0.1.tar.gz
Running django-authopenid-1.0.1/setup.py -q bdist_egg --dist-dir /tmp/easy_install-UtVC7d/django-authopenid-1.0.1/egg-dist-tmp-oWjnYf
warning: no files found matching 'CHANGES.MD'
Sorry: TypeError: ('compile() expected string without null bytes',)
...
Adding django-authopenid 1.0.1 to easy-install.pth file
&nbsp;
Installed /usr/lib/python2.5/site-packages/django_authopenid-1.0.1-py2.5.egg
Processing dependencies for django-authopenid
Finished processing dependencies for django-authopenid</pre></div></div>

<h3>Prepare Django application environment</h3>
<p>There are several things you&#8217;d need to do:</p>
<ol>
<li>Create directory for application files</li>
<p>I will use /var/app/application/ in this example</p>
<li>Create directory for static content such as JS, CSS, HTML and images</li>
<p>I will use /var/www/application/ in this example</p>
<li>If you are using Apache web server add Virtual host definition and specify where web root is and when to pass control to mod_python module (note that all requests that do not start with /static/ will be passed to Django):</li>
<pre>    ServerName test.example.com
    DocumentRoot /var/www/application/
    ErrorLog /var/log/apache2/application-error.log
    CustomLog /var/log/apache2/application-access.log combined
    SetHandler mod_python
    PythonHandler django.core.handlers.modpython
    PythonPath sys.path+['/var/app/']
    SetEnv DJANGO_SETTINGS_MODULE application.settings
    SetEnv PYTHON_EGG_CACHE /tmp
    &lt;Location "/static/"&gt;
        SetHandler None
    &lt;/Location&gt;</pre>
<li>Also create database and configure appropriately in settings.py.</li>
<li>Enable administration application for Django</li>
</ol>
<h3 style="font-size: 1.17em;">Enable OpenID support</h3>
<p>These were the basic steps to get your Django environment set-up, now let&#8217;s enable OpenID module:</p>
<ol>
<li>In settings.py add OpenID middleware, application and also tell Django where to find templates</li>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">MIDDLEWARE_CLASSES = <span style="color: black;">&#40;</span>
    ...
    <span style="color: #483d8b;">'django_authopenid.middleware.OpenIDMiddleware'</span>,
<span style="color: black;">&#41;</span>
INSTALLED_APPS = <span style="color: black;">&#40;</span>
    ...
    <span style="color: #483d8b;">'django_authopenid'</span>,
    <span style="color: #483d8b;">'registration'</span>,
<span style="color: black;">&#41;</span>
LOGIN_URL = <span style="color: #483d8b;">&quot;/account/signin/&quot;</span>
TEMPLATE_DIRS = <span style="color: black;">&#40;</span>
    ...
    <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span>__file__<span style="color: black;">&#41;</span>, <span style="color: #483d8b;">'templates'</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#41;</span></pre></div></div>

<li>In urls.py just include urls from django_authopenid package:</li>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">urlpatterns = patterns<span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span>,
    ...
    <span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^account/'</span>, include<span style="color: black;">&#40;</span><span style="color: #483d8b;">'django_authopenid.urls'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>,
<span style="color: black;">&#41;</span></pre></div></div>

<li>Add the following context processors list (majority is what&#8217;s loaded by default anyway, you just need to add one line, but since it&#8217;s a tuple, you cannot modify it, so you must redefine it):

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">TEMPLATE_CONTEXT_PROCESSORS = <span style="color: black;">&#40;</span>
   <span style="color: #483d8b;">'django.core.context_processors.auth'</span>,
   <span style="color: #483d8b;">'django.core.context_processors.debug'</span>,
   <span style="color: #483d8b;">'django.core.context_processors.i18n'</span>,
   <span style="color: #483d8b;">'django.core.context_processors.media'</span>,
   <span style="color: #483d8b;">'django.core.context_processors.request'</span>,
   <span style="color: #483d8b;">'django_authopenid.context_processors.authopenid'</span>,
<span style="color: black;">&#41;</span></pre></div></div>

</li>
<li>Copy templates from the examples folder. Of course you&#8217;ll want them eventually to be fully integrated with your site, so that they match styles or even be incorporated in other pages, but for now, let&#8217;s just use the ones provided with the package. Location of the example templates obviously depends on your Linux distribution. On my Debian installation it was in /usr/lib/python2.5/site-packages/django_authopenid-1.0.1-py2.5.egg/example/templates. Copy examples/ directory to your Django application directory.</li>
</ol>
<h3>Test it</h3>
<p>Once you&#8217;re done, test it. Navigate to http:///account/signin/ and if you followed this manual you should see something like this:</p>
<div id="attachment_474" class="wp-caption aligncenter" style="width: 310px"><img class="size-medium wp-image-474" title="openid-login" src="http://www.grenadepod.com/wp-content/uploads/2009/11/openid-login-300x162.png" alt="Django authopenid login screen" width="300" height="162" /><p class="wp-caption-text">Django authopenid login screen</p></div>
<p>You may wonder what the login prompt on the left side is doing there. This is because Django authopenId logoc is to associate your OpenId account with local account and use standard Django &#8220;registration&#8221; middleware classes to handle all user management functions. If user does not exist &#8211; after you have selected your OpenID URL you will be asked to provide local username. You don&#8217;t need to memorise nor use it &#8211; it&#8217;s just to allow authopenId create association.</p>
<p>This may feel bit unintuitive, and I don&#8217;t particularly like this. I&#8217;m going to make some changes so that internal association is hidden from the end user and happens behind the scenes. This way my users are going to see only OpenId selector and login screen.</p>


<p>Related posts:<ol><li><a href='http://www.grenadepod.com/2009/12/13/python-web-crawler/' rel='bookmark' title='Permanent Link: Python web crawler'>Python web crawler</a></li>
<li><a href='http://www.grenadepod.com/2009/11/09/how-to-use-generic-views-in-django/' rel='bookmark' title='Permanent Link: How to use generic views in Django'>How to use generic views in Django</a></li>
<li><a href='http://www.grenadepod.com/2009/12/03/building-and-running-google-chrome-os-on-virtualbox/' rel='bookmark' title='Permanent Link: Building and running Google Chrome OS on VirtualBox'>Building and running Google Chrome OS on VirtualBox</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.grenadepod.com/2009/11/22/using-openid-for-authentication-in-django/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Query data from Django site with jQuery</title>
		<link>http://www.grenadepod.com/2009/11/13/query-data-from-django-site-with-jquery/</link>
		<comments>http://www.grenadepod.com/2009/11/13/query-data-from-django-site-with-jquery/#comments</comments>
		<pubDate>Fri, 13 Nov 2009 16:06:37 +0000</pubDate>
		<dc:creator>pulegium</dc:creator>
				<category><![CDATA[IT Technology]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.grenadepod.com/?p=331</guid>
		<description><![CDATA[Right, here&#8217;s what I needed to do: I have a list of IP addresses displayed on a web page and I want to show the status of every each of them. By &#8220;status&#8221; I mean just perform a simple ping and display OK next to the IP, or &#8216;no response&#8217; otherwise. Listing is a Django [...]


Related posts:<ol><li><a href='http://www.grenadepod.com/2009/11/09/how-to-use-generic-views-in-django/' rel='bookmark' title='Permanent Link: How to use generic views in Django'>How to use generic views in Django</a></li>
<li><a href='http://www.grenadepod.com/2009/11/18/developing-my-first-wordpress-plugin/' rel='bookmark' title='Permanent Link: Developing my first WordPress plugin'>Developing my first WordPress plugin</a></li>
<li><a href='http://www.grenadepod.com/2009/11/22/using-openid-for-authentication-in-django/' rel='bookmark' title='Permanent Link: Using OpenID for authentication in Django'>Using OpenID for authentication in Django</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p id="top" />Right, here&#8217;s what I needed to do: I have a list of IP addresses displayed on a web page and I want to show the status of every each of them. By &#8220;status&#8221; I mean just perform a simple ping and display OK next to the IP, or &#8216;no response&#8217; otherwise.</p>
<p>Listing is a Django application, so theoretically I could just go through the list of IPs, ping and add status to the list that gets passed to Django template. But nice it is not. It might take ages to query the whole list, and even if I spend time implementing multithreaded ping and ping them all concurrently it still going to take at leas couple of seconds to complete.</p>
<p>So obvious choice is to delay the ping action. I will serve the page with all IPs and other bits and pieces and then let my JavaScript to do the AJAX magic.</p>
<p>So, how do I do that?</p>
<p>Well, first I need a view that checks if the given IP responds to a ping and displays the result. To keep things simple, I&#8217;m going to return a string, which will be displayed on the list page:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> ping<span style="color: black;">&#40;</span>request, address=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> responding_to_ping<span style="color: black;">&#40;</span>address<span style="color: black;">&#41;</span>:
        msg = <span style="color: #483d8b;">&quot;Ping OK&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        msg = <span style="color: #483d8b;">&quot;No response&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> HttpResponse<span style="color: black;">&#40;</span>msg<span style="color: black;">&#41;</span></pre></div></div>

<p>I then need to add URL pattern, so I can call the view:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">    url<span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^ping/(?P&lt;address&gt;<span style="color: #000099; font-weight: bold;">\d</span>{1,3}<span style="color: #000099; font-weight: bold;">\.</span><span style="color: #000099; font-weight: bold;">\d</span>{1,3}<span style="color: #000099; font-weight: bold;">\.</span><span style="color: #000099; font-weight: bold;">\d</span>{1,3}<span style="color: #000099; font-weight: bold;">\.</span><span style="color: #000099; font-weight: bold;">\d</span>{1,3})/$'</span>, views.<span style="color: black;">ping</span><span style="color: black;">&#41;</span>,</pre></div></div>

<p>Good, so now I can navigate to http://<hostname>/ping/<ip_address>/ and it&#8217;ll come back with either &#8220;Ping OK&#8221; or &#8220;No response&#8221; message.<br />
Right, now let&#8217;s add some JavaScript magic that&#8217;ll query the server and update my web page with details.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">&lt;script type=&quot;text/javascript&quot; src=&quot;/static/js/jquery-1.3.2.min.js&quot;&gt;&lt;/script&gt;
<span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;</span>
    $<span style="color: #009900;">&#40;</span>document<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">ready</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;.address&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">each</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #003366; font-weight: bold;">var</span> curId <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'id'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            updateStatus<span style="color: #009900;">&#40;</span>curId<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #003366; font-weight: bold;">function</span> updateStatus<span style="color: #009900;">&#40;</span>attrId<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        address <span style="color: #339933;">=</span> attrId.<span style="color: #660066;">replace</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'ip_'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        address <span style="color: #339933;">=</span> address.<span style="color: #660066;">replace</span><span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/_/g</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'.'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        $.<span style="color: #660066;">ajax</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
            url<span style="color: #339933;">:</span> <span style="color: #3366CC;">'/ping/'</span> <span style="color: #339933;">+</span> address<span style="color: #339933;">,</span>
            success<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>response<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#'</span> <span style="color: #339933;">+</span> attrId<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">html</span><span style="color: #009900;">&#40;</span>response<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #339933;">&lt;/</span>script<span style="color: #339933;">&gt;</span></pre></td></tr></table></div>

<p>So, what exactly is happening here?</p>
<ul>
<li><strong>Line 3:</strong> This waits for a document too load and call the callback function when ready to proceed, calback function defined in the lines below</li>
<li><strong>Lines 4-6:</strong>Goes through each element of the HTML document (my web page) that are of class &#8220;address&#8221;, extracts the element&#8217;s &#8216;id&#8217; attribute, and calls &#8216;updateStatus&#8217; function passing the &#8216;id&#8217; to it. So all elements that are going to be updated should look like: &lt;span class=&#8221;address&#8221; id=&#8221;ip_address&#8221; /&gt;</li>
<li><strong>Lines 11-12:</strong> All id&#8217;s are going to be in the following format: ip_1_2_3_4, so before I pass this to the URL, I need to strip the ip_ bit, and replace underscores with dots.</li>
<li><strong>Lines 13-17:</strong> This is where I perform AJAX call to the URL. The &#8216;success&#8217; bit is a call to the function that gets executed when the result is successfully retrieved. This function is pretty simple, it just replaces the contents of the tag with whatever it receives from the server</li>
</ul>
<p>And this is it, all that is left to do is list all IPs that need checking. Below is the raw HTML, but I trust you can be creative in writing a decent Django template to generate the page.</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;ul&gt;
    &lt;li&gt;192.168.0.1 [Status: &lt;span class=&quot;address&quot; id=&quot;ip_192_168_0_1&quot;&gt;Unknown&lt;/span&gt; ]&lt;/li&gt;
    &lt;li&gt;192.168.0.2 [Status: &lt;span class=&quot;address&quot; id=&quot;ip_192_168_0_2&quot;&gt;Unknown&lt;/span&gt; ]&lt;/li&gt;
    &lt;li&gt;192.168.0.3 [Status: &lt;span class=&quot;address&quot; id=&quot;ip_192_168_0_3&quot;&gt;Unknown&lt;/span&gt; ]&lt;/li&gt;
    ...
&lt;/ul&gt;</pre></div></div>



<p>Related posts:<ol><li><a href='http://www.grenadepod.com/2009/11/09/how-to-use-generic-views-in-django/' rel='bookmark' title='Permanent Link: How to use generic views in Django'>How to use generic views in Django</a></li>
<li><a href='http://www.grenadepod.com/2009/11/18/developing-my-first-wordpress-plugin/' rel='bookmark' title='Permanent Link: Developing my first WordPress plugin'>Developing my first WordPress plugin</a></li>
<li><a href='http://www.grenadepod.com/2009/11/22/using-openid-for-authentication-in-django/' rel='bookmark' title='Permanent Link: Using OpenID for authentication in Django'>Using OpenID for authentication in Django</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.grenadepod.com/2009/11/13/query-data-from-django-site-with-jquery/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>How to use generic views in Django</title>
		<link>http://www.grenadepod.com/2009/11/09/how-to-use-generic-views-in-django/</link>
		<comments>http://www.grenadepod.com/2009/11/09/how-to-use-generic-views-in-django/#comments</comments>
		<pubDate>Mon, 09 Nov 2009 23:05:45 +0000</pubDate>
		<dc:creator>pulegium</dc:creator>
				<category><![CDATA[IT Technology]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.grenadepod.com/?p=256</guid>
		<description><![CDATA[This is my first &#8220;technical&#8221; post here, so bear with me on this one. Sooner or later in your Django development career you&#8217;ll notice that you keep on repeating and implementing same views over and over again: list objects display details for any particular object add/delete/modify the object When I was reading about Django, I&#8217;ve [...]


Related posts:<ol><li><a href='http://www.grenadepod.com/2009/11/13/query-data-from-django-site-with-jquery/' rel='bookmark' title='Permanent Link: Query data from Django site with jQuery'>Query data from Django site with jQuery</a></li>
<li><a href='http://www.grenadepod.com/2009/12/13/python-web-crawler/' rel='bookmark' title='Permanent Link: Python web crawler'>Python web crawler</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p id="top" />This is my first &#8220;technical&#8221; post here, so bear with me on this one.</p>
<p>Sooner or later in your Django development career you&#8217;ll notice that you keep on repeating and implementing same views over and over again:</p>
<ul>
<li>list objects</li>
<li>display details for any particular object</li>
<li>add/delete/modify the object</li>
</ul>
<p>When I was reading about Django, I&#8217;ve noticed something mentioned that was called &#8220;generic views&#8221;, but at that time it somehow escaped me, and I wrote numerous views, just to implement those functions I mentioned above. In some extreme cases I&#8217;ve had 3-4 different views, effectivelly implementing the same for different models.</p>
<p>So the time came to educate myself and learn about &#8220;generic views&#8221; that are designed to do just that: implement basic and common tasks, so you don&#8217;t have to write a single line of code.</p>
<p>Now let&#8217;s start with the model definition. Suppose I have the following model class:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Rule<span style="color: black;">&#40;</span>models.<span style="color: black;">Model</span><span style="color: black;">&#41;</span>:
    rule = models.<span style="color: black;">TextField</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    description = models.<span style="color: black;">CharField</span><span style="color: black;">&#40;</span>max_length=<span style="color: #ff4500;">400</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__unicode__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">description</span><span style="color: black;">&#91;</span>:<span style="color: #ff4500;">20</span><span style="color: black;">&#93;</span></pre></div></div>

<p>First of all I need to import generic view functions from the Django libraries, here&#8217;s what you need to add to your urls.py file:</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;">views</span>.<span style="color: black;">generic</span> <span style="color: #ff7700;font-weight:bold;">import</span> list_detail, create_update</pre></div></div>

<p><em>list_detail</em> provides two methods that are used to represent data:</p>
<ul>
<li><strong>object_list</strong> &#8211; to display a list of objects</li>
<li><strong>object_detail</strong> &#8211; to display details about any given object</li>
</ul>
<p><em>create_update</em> provides three methods to manipulate data:</p>
<ul>
<li><strong>create_object</strong> &#8211; creates new object</li>
<li><strong>update_object</strong> &#8211; modifies existing object</li>
<li><strong>delete_object</strong> &#8211; deletes any given object</li>
</ul>
<p>I then need to define a <em>queryset</em> dictionary that contains a list of objects which generic views will operate upon. Add this to your <em>urls.py</em>:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">rule_info = <span style="color: black;">&#123;</span>
    <span style="color: #483d8b;">'queryset'</span>: Rule.<span style="color: black;">objects</span>.<span style="color: #008000;">all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>,
    <span style="color: #483d8b;">'template_name'</span>: <span style="color: #483d8b;">'display_rule.html'</span>,
<span style="color: black;">&#125;</span></pre></div></div>

<p>The only required field here is the queryset, others are optional. You don&#8217;t even need to define a template name as Django will automatically generate one. If you omit <em>template_name</em>, it will attempt to load a template <em>&lt;app_label&gt;/&lt;model_name&gt;_form.html</em>.</p>
<p>Right, now I&#8217;ll do the display bit first. Add the following URL patterns (as you might already guessed it, to ulrs.py file):</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">url<span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^rule/$'</span>, list_detail.<span style="color: black;">object_list</span>, rule_info, name=<span style="color: #483d8b;">'rule-displaytop'</span><span style="color: black;">&#41;</span>,
url<span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^rule/(?P&lt;object_id&gt;<span style="color: #000099; font-weight: bold;">\d</span>+)/, list_detail.object_detail, rule_info, name='</span>rule-display<span style="color: #483d8b;">'),</span></pre></div></div>

<p>As you can see, I instruct urls.py to call generic views <em>list_detail.object_list</em> and <em>list_detail.object_list</em> and also pass my <em>rule_info</em> dictionary as an argument. The dictionary contains a list of all objects that interest me. List view would simply pass the list on to the template, and the detailed view would select an individual object and pass it on to the template. Therefore the detailed view also expects <em>object_id</em> (which must be a primary key), so that it can find the required object.</p>
<p>When views call templates to display the information, they pass object list as <em>object_list</em> template variable and an instance of any object as <em>object</em>. You can override this by adding <em>template_object_name</em> to the dictionary and setting it to any name you like. If you set it to <em>foo</em>, the names would become: <em>foo_list</em> and <em>foo</em>. For now I leave it as it is. Below is my display_rule.html template:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">{% extends &quot;base.html&quot; %}
{% block contents %}
  {% if object %}
    &lt;h1&gt;Rules details&lt;/h1&gt;
    &lt;ul&gt;
      &lt;li&gt;ID: {{ object.id }}&lt;/li&gt;
      &lt;li&gt;Description: {{ object.description }}&lt;/li&gt;
      &lt;li&gt;Rule text:
          {{ object.rule }}
      &lt;/li&gt;
    &lt;/ul&gt;
    ( &lt;a href=&quot;{% url rule-modify object.id %}&quot;&gt;modify&lt;/a&gt; |
      &lt;a href=&quot;{% url rule-delete object.id %}&quot;&gt;delete&lt;/a&gt; )
  {% else %}
    &lt;h1&gt;List of all Rules&lt;/h1&gt;
    {% if object_list %}
      &lt;ul&gt;
        {% for rule in object_list %}
          &lt;li&gt;{{ rule.description }} ( &lt;a href=&quot;{% url rule-display rule.id %}&quot;&gt;details&lt;/a&gt; |
                                       &lt;a href=&quot;{% url rule-modify rule.id %}&quot;&gt;modify&lt;/a&gt; |
                                       &lt;a href=&quot;{% url rule-delete rule.id %}&quot;&gt;delete&lt;/a&gt; )&lt;/li&gt;
        {% endfor %}
      &lt;/ul&gt;
    {% else %}
      No rules defined yet.
    {% endif %}
  &lt;h3&gt;&lt;a href=&quot;{% url rule-add %}&quot;&gt;Add new rule&lt;/a&gt;&lt;/h3&gt;
{% endif %}
{% endblock %}</pre></div></div>

<p>As you can see the logic is somewhat simple:</p>
<ul>
<li>Check if the template object <em>object</em> is defined</li>
<li>If it is, that means we&#8217;ve been called from the detailed object view method and so need to display object information</li>
<li>If not, then we&#8217;ve been called from the object list view, so we need to iterate through the list</li>
<li>Check if the list is not empty (very important! as the lists tend to come empty in some cases&#8230;)</li>
<li>If the list is not empty &#8211; display all objects and provide links to basic functions</li>
</ul>
<p>Let&#8217;s start with adding new objects. You will need to define <em>get_absolute_url</em> method for your class (this will be used to get a URL where to redirect the user once the form has been submitted) and also define Model Form class (not required, strictly speaking, but I like to define it, so that I don&#8217;t need to if I decide to change form behaviour). This is how these two classes are going to look now:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Rule<span style="color: black;">&#40;</span>models.<span style="color: black;">Model</span><span style="color: black;">&#41;</span>:
    rule = models.<span style="color: black;">TextField</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    description = models.<span style="color: black;">CharField</span><span style="color: black;">&#40;</span>max_length=<span style="color: #ff4500;">400</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__unicode__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">description</span><span style="color: black;">&#91;</span>:<span style="color: #ff4500;">20</span><span style="color: black;">&#93;</span>
&nbsp;
    @models.<span style="color: black;">permalink</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> get_absolute_url<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'rule-display'</span>, <span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#123;</span><span style="color: #483d8b;">'object_id'</span>: <span style="color: #008000;">self</span>.<span style="color: #008000;">id</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> RuleForm<span style="color: black;">&#40;</span>ModelForm<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">class</span> Meta:
        model = Rule</pre></div></div>

<p>For now ignore the &#8220;magic&#8221; with URL names, these are used to help reverse URL resolver, and I&#8217;m going to talk about these in other posts. Just note that <em>get_absolute_url</em> returns generated URL with <em>object_id</em> embedded in it.</p>
<p><em>add.html</em> template is very simplistic and contains only few lines:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;form action=&quot;.&quot; method=&quot;POST&quot;&gt;
{{ form.as_p }}
&lt;input type=&quot;submit&quot; value=&quot;Add&quot; /&gt;
&lt;/form&gt;</pre></div></div>

<p>This is enough to display all fields and a submit button. If you need anything fancier than that, you&#8217;d need to alter the form to suit your needs.</p>
<p>Next, I&#8217;ll need to define a dictionary with settings, which will be passed to generic create and modify views, just like a queryset dictionary was used with display views:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">rule_form = <span style="color: black;">&#123;</span>
  <span style="color: #483d8b;">'form_class'</span>: RuleForm,
  <span style="color: #483d8b;">'template_name'</span>: <span style="color: #483d8b;">'add.html'</span>,
<span style="color: black;">&#125;</span></pre></div></div>

<p>And finally some URL patterns to handle the requests:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">url<span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^rule/(?P&lt;object_id&gt;<span style="color: #000099; font-weight: bold;">\d</span>+)/modify/$'</span>, create_update.<span style="color: black;">update_object</span>, rule_form, name=<span style="color: #483d8b;">'rule-modify'</span><span style="color: black;">&#41;</span>,
url<span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^rule/add/$'</span>, create_update.<span style="color: black;">create_object</span>, rule_form, name=<span style="color: #483d8b;">'rule-add'</span><span style="color: black;">&#41;</span>,</pre></div></div>

<p>As you can see, these two are very similar with one exception, <em>update_object</em> requires <em>object_id</em>, which is embedded in the URL, so you don&#8217;t need to worry about it.<br />
Finally let&#8217;s sort out the delete object function. This function requires three fields: model name, post delete redirect and also a confirmation template name. All defined in a dictionary form:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">rule_delete = <span style="color: black;">&#123;</span>
  <span style="color: #483d8b;">'model'</span>: Rule,
  <span style="color: #483d8b;">'post_delete_redirect'</span>: <span style="color: #483d8b;">'../..'</span>,
  <span style="color: #483d8b;">'template_name'</span>: <span style="color: #483d8b;">'delete_confirm_rule.html'</span>,
<span style="color: black;">&#125;</span></pre></div></div>

<p>You also need additional URL pattern:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">url<span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^rule/(?P&lt;object_id&gt;<span style="color: #000099; font-weight: bold;">\d</span>+)/delete/$, create_update.delete_object, rule_delete, name='</span>rule-delete<span style="color: #483d8b;">'),</span></pre></div></div>

<p>Confirmation template just asks for a user confirmation and redirects to the same URL, however the method is POST, so the view knows it needs to delete the object rather than display the confirmation page (which happens if the request is GET):</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;form method=&quot;post&quot; action=&quot;.&quot;&gt;
&lt;p&gt;Are you sure?&lt;/p&gt;
&lt;input type=&quot;submit&quot; /&gt;
&lt;/form&gt;</pre></div></div>

<p>This is it, now you know how to perform some of the common tasks without writing any views.</p>


<p>Related posts:<ol><li><a href='http://www.grenadepod.com/2009/11/13/query-data-from-django-site-with-jquery/' rel='bookmark' title='Permanent Link: Query data from Django site with jQuery'>Query data from Django site with jQuery</a></li>
<li><a href='http://www.grenadepod.com/2009/12/13/python-web-crawler/' rel='bookmark' title='Permanent Link: Python web crawler'>Python web crawler</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.grenadepod.com/2009/11/09/how-to-use-generic-views-in-django/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
