Archive for July, 2009

Django: Testing With File System Side Effects

Thursday, July 30th, 2009

Django uses unittest for testing. django.test.TestCase is a special base class for tests that adds various features1. Django testing framework takes care of creating a test database, resetting it to its initial state after each test and finally destroying it. So you don’t have to worry tests overwriting anything in your main database.

But if your tests need to create, modify or delete files you need to make sure these side effects are contained. For instance if one of your applications is generating or uploading files within your MEDIA_PATH you would rather not let it mess with files already there.

Here is a little example of using a temporary folder for such operations:

   1 import shutil
   2 import tempfile
   3 from django.test import TestCase
   4 
   5 
   6 class FooTestCase(TestCase):
   7     def setUp(self):
   8         self.__old_foo_dir = settings.FOO_DIR
   9         settings.FOO_DIR = tempfile.mkdtemp(suffix='foo')
  10 
  11     def test_foo(self):
  12         # some tests with filesystem side effects
  13         pass
  14 
  15     def tearDown(self):
  16         shutil.rmtree(settings.FOO_DIR)
  17         settings.FOO_DIR = self.__old_foo_dir

Here tempfile.mkdtemp() creates a temporary directory for us and returns its path. When we are finished we remove this temporary directory with shutil.rmtree() and restore our setting FOO_DIR back to its original value. It is always best to clean up thoroughly. We don’t want our tests to fail because of themselves.

Assume settings.FOO_DIR was a directory under MEDIA_PATH. So when you diverted FOO_DIR to the temporary directory, files within couldn’t be served with media server or your development server (if you have configured it to serve static files). If for some reason you need these files accessible over HTTP you need to re-configure your media server. In case of development server it is relatively easy; just divert whole MEDIA_PATH and copy needed files to temporary directory. I suppose you can get away without copying static files to the new location in case of a real media server, nevertheless configuration will be somewhat difficult and a restart might be necessary.


1: For more information you can refer to official documentation.

Bookmark and Share

django-renderformplain

Sunday, July 26th, 2009

django-renderformplain is a Django app that allows you to render forms in plain text. I have found myself implementing quite a bit of styling into my forms and thought why do it once more when I want to render just the data. Renderformplain works both with bound forms (renders bound data) and unbound forms (renders initial data). The project is new, so there is no release yet1. But I’d like you to try it out and tell me what you think about it. And maybe find a few bugs.

An Example

After you copy renderformplain folder somewhere within your PYTHONPATH, add "renderformplain" to your INSTALLED_APPS setting to be able to run the example.

Let’s say you have a model File:

   1 class File(models.Model):
   2     name = models.CharField(max_length=100)
   3     path = models.CharField(max_length=250)
   4     size = models.IntegerField()
   5     last_modified = models.DateTimeField(default=datetime.datetime.now)
   6     created = models.DateTimeField(default=datetime.datetime.now)
   7     permissions = models.IntegerField()

And a form FileForm:

   1 class FileForm(forms.ModelForm):
   2     class Meta:
   3         model = File

Now assume you are using django.contrib.formtools.preview.FormPreview to review entered data before saving. In your formtools/preview.html template, instead of rendering the form as an HTML form, you can render it in plain text like this:

{% load renderformplain_tags %}

{% plainform form as plain_form %}

<h1>Preview your submission</h1>
{{ plain_form.as_table }}

<form action="" method="post">
  {{ form.as_hidden }}
  <input type="hidden" name="{{ stage_field }}" value="2" />
  <input type="hidden" name="{{ hash_field }}" value="{{ hash_value }}" />
  <p><input type="submit" value="Submit" /></p>
</form>

This will render the plain_form just like a normal form, except all fields will be replaced with read-only plain text.

Anyway. Try renderformplain and tell me what you think.


1: I will tag releases. Check out the repository for tags.

Bookmark and Share