<?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/"
	>

<channel>
	<title>SamuraiBlog.com &#187; django</title>
	<atom:link href="http://samuraiblog.com/wordpress/tag/django/feed/" rel="self" type="application/rss+xml" />
	<link>http://samuraiblog.com/wordpress</link>
	<description>Cursing and Cigarettes</description>
	<pubDate>Sat, 24 Apr 2010 01:36:47 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Web Console and Browser Added to django-json-rpc</title>
		<link>http://samuraiblog.com/wordpress/2009/11/07/django-json-rpc-web-console/</link>
		<comments>http://samuraiblog.com/wordpress/2009/11/07/django-json-rpc-web-console/#comments</comments>
		<pubDate>Sun, 08 Nov 2009 04:48:41 +0000</pubDate>
		<dc:creator>Samuel Sutch</dc:creator>
		
		<category><![CDATA[Articles]]></category>

		<category><![CDATA[Code]]></category>

		<category><![CDATA[development]]></category>

		<category><![CDATA[django]]></category>

		<category><![CDATA[django-json-rpc]]></category>

		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://samuraiblog.com/wordpress/?p=218</guid>
		<description><![CDATA[This morning I put the finishing touches on the web console and service browser for <a href="http://github.com/samuraisam/django-json-rpc">django-json-rpc</a>. It's a fully-bundled utility to aid in rapid development of your web service. It's available on github now and will be a published to PyPI soon as I work out one more interface bug. A <a href="http://logjamm.in/django-json-rpc/json/browse/">live demo</a> is available. Screen after the jump.]]></description>
			<content:encoded><![CDATA[<p>This morning I put the finishing touches on the web console and service browser for <a href="http://github.com/samuraisam/django-json-rpc">django-json-rpc</a>. It&#8217;s a fully-bundled utility to aid in rapid development of your web service. It&#8217;s available on github now and will be a published to PyPI soon as I work out one more interface bug. A <a href="http://logjamm.in/django-json-rpc/json/browse/">live demo</a> is available. Check it out:</p>
<p><img src="http://samuraiblog.com/wordpress/wp-content/uploads/2009/11/jsonrpcbrowserscreen.png" alt="jsonrpcbrowserscreen" title="jsonrpcbrowserscreen" width="504" height="639" class="aligncenter size-full wp-image-226" /></p>
]]></content:encoded>
			<wfw:commentRss>http://samuraiblog.com/wordpress/2009/11/07/django-json-rpc-web-console/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Django and JSON-RPC</title>
		<link>http://samuraiblog.com/wordpress/2009/11/03/django-and-json-rpc/</link>
		<comments>http://samuraiblog.com/wordpress/2009/11/03/django-and-json-rpc/#comments</comments>
		<pubDate>Tue, 03 Nov 2009 09:47:36 +0000</pubDate>
		<dc:creator>Samuel Sutch</dc:creator>
		
		<category><![CDATA[Articles]]></category>

		<category><![CDATA[Code]]></category>

		<category><![CDATA[django]]></category>

		<category><![CDATA[django-json-rpc]]></category>

		<category><![CDATA[python]]></category>

		<category><![CDATA[tutorials]]></category>

		<guid isPermaLink="false">http://samuraiblog.com/wordpress/?p=167</guid>
		<description><![CDATA[In application development, I&#8217;ve yet to be the bearer of a product who&#8217;s primary functionality has not been aided or entirely supported by a central web application. It is uncommon for developers in this situation to have the luxury of using a common programming language between server and client implementations. A lot of developers will [...]]]></description>
			<content:encoded><![CDATA[<p>In application development, I&#8217;ve yet to be the bearer of a product who&#8217;s primary functionality has not been aided or entirely supported by a central web application. It is uncommon for developers in this situation to have the luxury of using a common programming language between server and client implementations. A lot of developers will end up rolling their own RPC which evolves over the lifetime of the product to meet its needs. This puts unneeded strain on the developer to fulfill the role of RPC expert as well as interface designer, and expert-everything-else.</p>
<p>I have done many primarily-RPC web applications using tomcat or PHP or twisted, but by far the best way is using Python and Django. However, I have always viewed the state of RPC in Django broken. While using Django for all sorts of other web application purposes is incredibly easy, getting started with RPC presents a lot more friction.</p>
<p>Introducing <a href="http://github.com/samuraisam/django-json-rpc">django-json-rpc</a>, a very easy way to expose your web application to the world of integrated applications.</p>
<p>Installation is as simple as:</p>
<pre lang="shell">
  easy_install django-json-rpc
</pre>
<p>Add a mount point to your <code>urls.py</code> file and import django-json-rpc.</p>
<pre lang="python">
  from jsonrpc import jsonrpc_site

  urlpatterns += patterns('',
    (r'^json/', jsonrpc_site.dispatch)
  )
</pre>
<p>The interface to django-json-rpc is exposed through only one function - the <code>jsonrpc_method</code> decorator. Functions that use this decorator may be placed anywhere in the source tree and need only import <code>jsonrpc.jsonrpc_method</code>.</p>
<pre lang="python">
  from jsonrpc import jsonrpc_method

  @jsonrpc_method('app.sayHello')
  def say_hello(request, name):
    return "Hello, " + name
</pre>
<p>To hook your views into the default jsonrpc site, they must simply be imported somewhere by Django. The best place for this is in your <code>urls.py</code> file, which should now look something like this:</p>
<pre lang="python">
  from jsonrpc import jsonrpc_site
  import myapp.views

  urlpatterns += patterns('',
    (r'^json/', jsonrpc_site.dispatch)
  )
</pre>
<p>Test your service with the provided Proxy:</p>
<pre lang="shell">
  ./manage.py runserver 8080

  ./manage.py shell
</pre>
<pre lang="python">
  >>> from jsonrpc.proxy import ServiceProxy
  >>> s = ServiceProxy('http://localhost:8080/json/')
  >>> s.app.sayHello('Sam')
  {u'error': None, u'id': u'jsonrpc', u'result': u'Hello Sam'}
</pre>
<h3>HTTP GET</h3>
<p>Django-json-rpc supports JSON-RPC version 1.1 which includes support for HTTP GET, meaning, all your REST are belong to us as well. Add the HTTP GET mount point to your <code>urls.py</code> file:</p>
<pre lang="python">
  from jsonrpc import jsonrpc_site
  import myapp.views

  urlpatterns += patterns('',
    (r'^json/', jsonrpc_site.dispatch),
    (r'^json/(?P<method>[a-zA-Z0-9.]+)$', jsonrpc_site.dispatch)
  )
</method></pre>
<p>It is required by django-json-rpc to mark each method safe for dispatch through HTTP GET. <code>jsonrpc_method('sayHello')</code> becomes:</p>
<pre lang="python">
  jsonrpc_method('app.sayHello', safe=True)
</pre>
<p>Now your method will be available at <code>http://localhost:8080/json/app.sayHello?name=Sam</code>. HTTP GET requests only support string and number typed arguments.</p>
<h3>Authentication</h3>
<p>The django-json-rpc package also supports authentication, by default using <code>django.contrib.auth</code>&#8217;s model backend - the <code>User</code> object we&#8217;re all so familiar with, however you may provide any method, including using any authentication middleware. If you aren&#8217;t using middleware, <code>username</code> and <code>password</code> arguments will automatically be added to the beginning of the argument list for your method.</p>
<pre lang="python">
  @jsonrpc_method('app.sayHello', authenticated=True)
  def say_hello(request):
    return "Hello, " + request.user.first_name
</pre>
<pre lang="python">
  >>> s.app.sayHello('samuraiblog', 'password')
  {u'error': None, u'id': u'jsonrpc', u'result': u'Hello Sam'}
</pre>
<h3>Version Agnostic</h3>
<p>django-json-rpc will continue to work regardless of which version JSON-RPC client you happen to be using. It supports all argument types supported in JSON-RPC versions 1.0, 1.1 and 2.0, and will respond if a client specifies the version in either the <code>jsonrpc</code> or <code>version</code> key.</p>
<h3>Conclusion</h3>
<p>I have used this package for the development of several commercial iPhone applications and it has greatly improved my productivity in developing a web service backend. Up next? A django-xmlrpc? Haha! Fuck that!</p>
]]></content:encoded>
			<wfw:commentRss>http://samuraiblog.com/wordpress/2009/11/03/django-and-json-rpc/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Create a Long-Running-Process Server for Django</title>
		<link>http://samuraiblog.com/wordpress/2009/03/06/create-a-long-running-process-server-for-django/</link>
		<comments>http://samuraiblog.com/wordpress/2009/03/06/create-a-long-running-process-server-for-django/#comments</comments>
		<pubDate>Sat, 07 Mar 2009 07:47:58 +0000</pubDate>
		<dc:creator>Samuel Sutch</dc:creator>
		
		<category><![CDATA[Code]]></category>

		<category><![CDATA[development]]></category>

		<category><![CDATA[django]]></category>

		<category><![CDATA[multiprocessing]]></category>

		<category><![CDATA[programming]]></category>

		<category><![CDATA[python]]></category>

		<category><![CDATA[scaling]]></category>

		<guid isPermaLink="false">http://samuraiblog.com/wordpress/?p=127</guid>
		<description><![CDATA[Have you ever wanted to put up a server made exclusively to handle the expensive actions in your web app? In this article I will be showing you how to create a server to that will be set up to receive commands from your web server and process them in the context of your django [...]]]></description>
			<content:encoded><![CDATA[<p>Have you ever wanted to put up a server made exclusively to handle the expensive actions in your web app? In this article I will be showing you how to create a server to that will be set up to receive commands from your web server and process them in the context of your django web app. This technique could be used many places such as a desktop GUI application, or a web service architecture.</p>
<p>Say you have work unit  WU which takes <a title="python pickle module" href="http://docs.python.org/library/pickle.html" target="_blank">pickleable</a> arguments (a, b, c). If your work unit is thread-safe (it modifies no global variables, and causes no side effects in your application) it can be preformed on in another process, or even on another machine, allowing you to return control to the user immediately.</p>
<p>For example, I want to add the ability for a user to import their contacts using X contacts service:</p>
<p><strong>Fig 1: project/views.py</strong></p>
<pre lang="python" line="1">def import_contacts(request):
    from my.specialsauce.contacts import run_contacts_import
    contacts = run_contacts_import(request)
    return render_to_response('t/contacts-import.html', {'contacts': contacts})</pre>
<p>Currently, the view retrieves and imports the users contacts in the view, making the user wait until the operation has completed to see the returned page. What if we could implement this in a way which would return control to the user immediately, firing off run_contacts_import in another thread, another process, or even another server!</p>
<p>To do this we will need Django, <a href="http://pypi.python.org/pypi/multiprocessing">multiprocessing</a> and Python 2.5+. Now, I will assume you are already as far as <strong>Fig 1</strong>. Say a user with 10,000 contacts (or even 100) ambles along and imports their contacts. Both users are going to be waiting much longer than the average gmail-generation-web-user can be expected to wait. They will hit refresh, restarting this process and crashing your server.</p>
<p>Since the <a href="http://docs.djangoproject.com/en/dev/ref/request-response/">Django request</a> object is pickleable, we can pass it as an argument to another process using multiprocessing.</p>
<p><strong>Fig 2: project/views.py</strong></p>
<pre lang="python" line="1">from multiprocessing import Pool

m = Pool(10)

def import_contacts(request):
    # run_contacts_import will have to update request.session['CONTACT_IMPORT_STATUS']
    has_status = 'CONTACT_IMPORT_STATUS' in request.session
    status = has_status and request.session['CONTACT_IMPORT_STATUS'] == True
    if status is True:
        return HttpResponseRedirect('/import-finished/')
    elif not status and has_status:
        return render_to_response('t/contacts-import-not-finished.html', {})
    elif not has_status:
        from my.specialsauce.contacts import run_contacts_import
        m.apply_async(run_contacts_import, args=(request,))
        return render_to_response('t/contacts-import.html', {'contacts': contacts})</pre>
<p>This seems simple enough, and upon first inspection, seems to work rather decently. However, this adds a global variable to our Django process, which is a bad idea. Using this technique, it would be best to create a lock, spawn off a new thread, and acquire/release the lock while running apply_async (blegh). Unfortunately, this can eventually make your Django server unresponsive as many users come to run the expensive process (simply via system load). We need to move this process, and possibly a few others off our new server.</p>
<p>To do this, the Python multiprocessing package provides the high-level <a href="http://docs.python.org/library/multiprocessing.html#module-multiprocessing.managers">Manager</a> class. The Manager class is used to pipe commands between managers in different instances of the python interpreter.</p>
<h3>Create the Manager Class</h3>
<p>First, we need to create the Manager class that will eventually be implemented as our server. Create a file called managers.py in project/managers.py.</p>
<p><strong>Fig 3: project/managers.py</strong></p>
<pre lang="python" line="1">from multiprocessing.managers import BaseManager

from my.specialsauce.contacts import run_contacts_import

# This is the shared object. It simply implements a function which applies to the instance variable
# pool, which will be installed when the server is actually started (in a snippet below)
class ContactImporter(object):
    def __init__(self, pool=None):
        self.pool = pool

    def run_import(self, *args):
        self.pool.apply_async(run_contacts_import, args=args)

# instantiate the shared object
importer = ContactImporter()

# our manager
class CManager(BaseManager):
    pass

# you need to register a function which will return the shared object
# the shared object could be anything pickleable in python, in this case
# our new-style class descending from object
CManager.register('get_importer', callable=lambda:importer)</pre>
<h3>Create the Server</h3>
<p>We are going to be making a daemon server that we can start and stop using your projects manage.py file. To do this create a file called lrpserver.py in project/management/commands/lrpserver.py.</p>
<p><strong>Fig 4: project/management/commands/lrpserver.py</strong></p>
<pre lang="python" line="1">import os
import sys
import time
from optparse import make_option
from signal import SIGTERM

from multiprocessing import Pool

from django.core.management.base import BaseCommand
from django.conf import settings

from project.managers import CManager, importer

class Command(BaseCommand):
    option_list = BaseCommand.option_list + (
        make_option('--pidfile', dest='pidfile', default='', help="Specifies the PID file to use."),
        make_option('--start', dest='start', default='no', help='Starts the daemon'),
        make_option('--stop', dest='stop', default='no', help='Stops the daemon'),
        make_option('--restart', dest='restart', default='no', help='Restarts the daemon')
    )
    def handle(self, *args, **options):
        pidfile = options.get('pidfile')
        if not pidfile:
            print "--pidfile arg required"
            sys.exit(1)
        start = options.get('start')
        stop = options.get('stop')
        restart = options.get('restart')
        server = getattr(settings, 'LRP_SERVER_HOST', None)
        port = getattr(settings, 'LRP_SERVER_PORT', None)
        authkey = getattr(settings, 'LRP_SERVER_AUTHKEY', None)

        if server is None or port is None or authkey is None:
            print 'LRP_SERVER_HOST, LRP_SERVER_PORT and LRP_SERVER_AUTHKEY values required in settings file.'
            sys.exit(1)

        # This daemonizes our process and starts the server
        def _start():
            print 'Starting Long Running Process Server'
            from django.utils.daemonize import become_daemon
            become_daemon()
            fp = open(pidfile, "w")
            fp.write('%d\n' % os.getpid())
            fp.close()

            # set the pool that importer.run_import requires
            importer.pool = Pool(processes=10)
            # create an instance of CManager, get a server instance and start the server loop
            m = CManager(address=(server, port), authkey=authkey)
            s = m.get_server()
            s.serve_forever()

        def _stop():
            try:
                fp = open(pidfile, 'r')
                pid = int(fp.read().strip())
                fp.close()
            except IOError:
                pid = None
            if not pid:
                print 'Long Running Process Server Not Currently Running'
                return
            try:
                print 'Stopping Long Running Process Server'
                while 1:
                    os.kill(pid, SIGTERM)
                    time.sleep(0.1)
            except OSError, err:
                err = str(err)
                if err.lower().find('no such process') > 0:
                    if os.path.exists(pidfile):
                        os.remove(pidfile)
                else:
                    print err
                    sys.exit(1)

        def _restart():
            _stop()
            _start()

        if str(start) == 'yes':
            return _start()
        elif str(stop) == 'yes':
            return _stop()
        elif str(restart) == 'yes':
            return _restart()
        else:
            print 'Options: pidfile=%s start=%s stop=%s restart=%s' % (pidfile, start, stop, restart)
            print 'One of --(start|stop|restart)=yes is required.'
</pre>
<h3>Add the Required Settings to Your settings.py File</h3>
<p>The server and client require three settings, the host name of your server, the port on which the server is listening and the auth key of the required to access the server. In your settings.py file add the following with your values. For now, use the blank string &#8221; as the setting for host name. This instructs the server to serve from localhost. (Hint: If you do not know this value use socket.getfqdn()). </p>
<p><strong>Fig 5: settings.py</strong></p>
<pre lang="python" line="1">LRP_SERVER_HOST = ''
LRP_SERVER_PORT = 5667
LRP_SERVER_AUTHKEY = 'password'</pre>
<h3>Modify Your View Code</h3>
<p>To connect to the server, you must spawn a thread which creates an instance of the manager, connects and sends the command.</p>
<p><strong>Fig 6: project/views.py</strong></p>
<pre lang="python" line="1">from threading import Thread
from multiprocessing.managers import BaseManager

from django.conf import settings

class CManager(BaseManager):
    pass

CManager.register('get_importer')

# This function will become a thread which instantiates the Manager class,
# connects and starts the long running process
def _start_import_thread(request):
    gci_manager = CManager(address=(settings.GCI_SERVER_HOST, settings.GCI_SERVER_PORT),
                           authkey=settings.GCI_SERVER_AUTHKEY)
    gci_manager.connect()
    importer = gci_manager.get_importer()
    importer.run_import(request)

# This is not a view, it's a helper function which starts
# the thread above
def start_contacts_import(request):
    t = Thread(target=_start_import_thread, args=[request])
    t.setDaemon(True)
    t.start()

def import_contacts(request):
    # run_contacts_import will have to update request.session['CONTACT_IMPORT_STATUS']
    has_status = 'CONTACT_IMPORT_STATUS' in request.session
    status = has_status and request.session['CONTACT_IMPORT_STATUS'] == True
    if status is True:
        return HttpResponseRedirect('/import-finished/')
    elif not status and has_status:
        return render_to_response('t/contacts-import-not-finished.html', {})
    elif not has_status:
        start_contacts_import(request)
        return render_to_response('t/contacts-import.html', {'contacts': contacts})</pre>
<h3>Start the Server and Let it Fly!</h3>
<p>And finally we may start the server.</p>
<pre lang="bash" line="1">python manage.py lrpserver.py --pidfile=/home/django/run/lrp.pid --start=yes</pre>
<p>Now you can run your view.</p>
<h3>Follow-Up</h3>
<p>This process is applicable to more than just crawlers and contact importers. It can be used to minimize the load on your server for any number of tasks such as image and other file processing or running large database updates. The server can be <strong>put on another machine</strong> simply by duplicating your django installation on another machine and using that machine&#8217;s socket.getfqdn() (or ip address) value as the host name in your configs. You can also add a <strong>javascript status updater</strong> to notify the user of progress information related to their request.</p>
]]></content:encoded>
			<wfw:commentRss>http://samuraiblog.com/wordpress/2009/03/06/create-a-long-running-process-server-for-django/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
