Plug DB4O Into Django

As I continue to work with Django, I am coming to appreciate the elegance and simplicity of its design. Less Ruby on Rails style “magic” gives us more flexibility. You can store your models any way you like. Last weekend, I played with the possibility of using Couchdb, and I found an example that seemed easy to understand. (Couchdb is another open source project that I may write about later.)

There should be two steps to plugging DB4O into Django. First, we should be able to store settings in the settings.py file to specify where and how we will be storing our objects. The second step should be to create and use our models almost exactly as we would in a regular Django application. It should be that easy.

Editing Settings

It is not my goal to duplicate information you can get elsewhere. To find out how to set up a Django project, and to understand the files that are created for you, see the following tutorials.

In this entry, we are going to look at how to use the setting file in Django to store settings for DB4O. You can store anything in the settings file you like, and you can store these settings in separate settings files named prodsettings.py, devsettings.py etc. These settings are easy to retrieve from views and models.

We are going to make the following assumptions in our example: we only have one settings file, and it is called settings.py. Also, we are persisting objects to a file, and we are not using an object server.

A cllient/server mode is available in DB4O, and we will have to provide for it later. (DB4O client/server mode is covered in Chapter 8 of the book, The Definitive Guide to db4o. The chapter about client/server mode is available for free, if you are curious.)

To create settings, find your settings file, called settings.py, and add values. To see what entries look like, see below:

	# Django settings for mysite project.

	DEBUG = True
	TEMPLATE_DEBUG = DEBUG

	ADMINS = (
	    # ('Your Name', 'your_email@domain.com'),
	)

	MANAGERS = ADMINS

	DATABASE_ENGINE = ''
	DATABASE_NAME = '/path/to/file.db4o'
	DATABASE_USER = ''     # Not used with db4o in file mode.
	DATABASE_PASSWORD = '' # Not used with db4o in file mode.
	DATABASE_HOST = ''     # Not used with db4o in file mode.

	# Local time zone for this installation. Choices can be found here:
	# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
	# although not all choices may be available on all operating systems.
	# If running in a Windows environment this must be set to the same as your
	# system time zone.
	TIME_ZONE = 'America/Chicago'

	# Language code for this installation. All choices can be found here:
	# http://www.i18nguy.com/unicode/language-identifiers.html
	LANGUAGE_CODE = 'en-us'

        .  .  .  .  .  .  .

For our purposes, DATABASE_NAME will be the name of the file used by DB4O to persist objects. If you have read the DB4O documentation, you will know that you also have the option of running a server, in which case we could also use the DATABASE_HOST and DATABASE_PORT settings.

We also have the option of creating any settings we want to help us manage our application’s behavior. Django’s convention is to use capital letters for settings and to separate words with underscores.

At this point, we have enough information to find and connect to our DB4O file and we have stored it in the settings file. These settings will be used by our models to create objects and manage them. Our models will be written in such a way as to hide DB4O specific details from programmers. In my next installment, I will think about how to create a model for us to use with DB4O running in Django/Jython.

My thinking is that I will create my models in Jython, but I will create a command line script to create plain old Java objects (POJOs) and place them in a jar for us. I am lazy, and I always use Eclipse to create my jars for me. I expect to face some challenges at the command line, but I am up for it.

Therefore, the steps will be:

  1. Create models in a file called models.py.
  2. Run a command line command to generate a jar that contains classes for the the Java objects we want to persist. This jar will need to be in Jython’s classpath when the application runs. Corresponds to python manage.py syncdb for regular Django models.
  3. Build views, and use Django just as you would to create any other Django application.

The only difference will be in the behavior of the models, but our goal will be not to violate too many expectations. Regular Django models subclass django.db.models.Model, but ours will subclass DB4OModel, a class we will create. Our DB4O should resemble Django models as much as possible.

In my next installment, let’s look at DB4OModel. What does it need to look like?

Pythonic DB4O

Jim Huginin, the founder the Jython project, is credited with having said: “The purpose of a programming language is to let software developers express their intentions as simply and directly as possible.”

Unfortunately, we computer programmers are cursed by their own understanding of complexity. In fact, non-programmers often think complexity is a fundamental measure of our skill. The truth is that complexity is easier to achieve than simplicity. Simplicity is the Holy Grail of any framework or programming language.

I aspire to developing code that clearly and simply expresses my intentions. Simplicity is in the eye of the beholder, of course. Often, one paints oneself into a corner and then simplicity goes out the window. However, we am starting from scratch here, so let’s be hopeful.

My site stats indicate that few people have paid attention to the articles I posted by Dhananjay Nene. As I continue working with DB4O, I hope you get a chance to read these articles, especially the code examples.

The Project

For anyone who is jumping in late, the latest version of Jython, a version of Python that has been implement on the JVM, supports Django, a framework similar to Ruby on Rails. I want to demonstrate how to build a website, using Django to manage controllers and views, but I want to manage my models using DB4O.

Since I started writing about DB4O, my site has been getting visitors from about 50 different countries. But, there are few visitors from my own country, Canada. I find that interesting.

This Week

Django lets you replace parts of the framework very easily. In fact, I am quickly coming to appreciate this flexibility when I compare Django to other frameworks. Django does not force you to use its templating system, nor does it for you to use its data models. This is the flexibility we want to exploit to get DB4O working happily with Dajngo running on Jython.

This week, I want to concentrate on hiding DB40 from programmers who want to use DB4O to persist objects while using Django/Jython. The objects should save themselves, and the details should be administered from a central file. This is where I hope to get the most help from Jython as opposed to Java.

A Small Task

While I do this work, if anybody is interested in helping out, here is a task. I have managed to install Nginx on a server, and I have Django under Nginx running using FastCGI and regular Python, not Jython. To do this, I had to install Flup. My question is: can we install Flup under Jython? I would be happy to chat with anybody who either knows the answer, or is willing to investigate.

Otherwise, we will have to find another way – we could run Django in a servlet, and we could perhaps use Jetty. Any other options?

Jython: Formula One Tutorial: Part Three

In our first installment, we configured Eclipse to use Jython and DB4O, and we wrote some simple code to create Pilot objects and store them.

In our second installment, we used Jython to retrieve the objects we save in the first part of the tutorial. Now, we need to update and delete these objects.

Then we will have learned how to perform the four basic functions of persistent storage: create, retrieve, update and delete – often referred to as CRUD

This tutorial is based on the Formula One DB4O tutorial.

Updating objects

Updating objects is just as easy as storing them. In fact, you use the same set() method to update your objects: just call set() again after modifying any object.

Java Code:

    // updatePilot
    ObjectSet result=db.get(new Pilot("Michael Schumacher",0));
    Pilot found=(Pilot)result.next();
    found.addPoints(11);
    db.set(found);
    System.out.println("Added 11 points for "+found);
    retrieveAllPilots(db);

   OUTPUT:
    Added 11 points for Michael Schumacher/111
    2
    Michael Schumacher/111
    Rubens Barrichello/99

Jython Code:

    result=db.get(Pilot("Michael Schumacher",0))
    found=result.next()
    found.addPoints(11)
    db.set(found)
    print "Added 11 points for "+found
    retrieveAllPilots(db)

Notice that we query for the object first. This is an important point. When you call set() to modify a stored object, if the object is not ‘known’ (having been previously stored or retrieved during the current session), db4o will insert a new object. db4o does this because it does not automatically match up objects to be stored, with objects previously stored. It assumes you are inserting a second object which happens to have the same field values.

To make sure you’ve updated the pilot, please return to any of the retrieval examples above and run them again.

Deleting objects

Objects are removed from the database using the delete() method.

Java Code:

   // deleteFirstPilotByName

   ObjectSet result=db.get(new Pilot("Michael Schumacher",0));
   Pilot found=(Pilot)result.next();
   db.delete(found);
   System.out.println("Deleted "+found);
   retrieveAllPilots(db);

Jython Code:

   result=db.get(Pilot("Michael Schumacher",0))
   found=result.next()
   db.delete(found)
   print "Deleted ", found
   proto=Pilot(None,0)
   result=db.get(proto)
   listResult(result)

Let’s delete the other one, too.

    result=db.get(Pilot("Rubens Barrichello",0))
    found=result.next()
    db.delete(found)
    print "Deleted "+found
    proto=Pilot(None,0)
    result=db.get(proto)
    listResult(result)

Please check the deletion with the retrieval examples above.

As with updating objects, the object to be deleted has to be ‘known’ to db4o. It is not sufficient to provide a prototype object with the same field values.

Next Installment:

In our next installment, we will provide the full source code for this tutorial. We will also reflect on the differences between the Jython code and the Java code.

« Previous Entries Next Entries »