ModelForms good for importing too

If you have exported data from one database in plain text format and you want to import it to [Django][django], you should use a [`ModelForm` class][modelform] to do a lot of the heavy lifting for you.

A suitable `ModelForm` for your Django model will consume each row and do the conversion of each field to an appropriate Python type. Much simpler than explicitly converting each value yourself before creating a new model instance.

Suppose you have a model for an address book entry and its associated `ModelForm` (this works for Django 1.1):

# myapp/models.py
from django.db import models
from django import forms

class Contact(models.Model):
first_name = models.CharField(max_length=100)
second_name = models.CharField(max_length=100)
telephone = models.CharField(max_length=50, blank=True)
email = models.EmailField(blank=True)

class ContactForm(forms.ModelForm):
class Meta:
model = Contact

Here’s a script to run through a comma-separated list of contacts where each line looks something like “Smits, Jimmy, [email protected], 555-1234”:

from myapp.models import ContactForm

# Map columns to fields, adjusting the order as necessary
column_map = (
‘second_name’,
‘first_name’,
’email’,
‘telephone’,
)

for line in open(‘tab-separated-data.txt’):
row = dict(zip(column_map, (field.strip() for field in line.split(‘,’))))
form_obj = ContactForm(row)
try:
form_obj.save()
except ValueError:
for k, v in form_obj.errors.items():
print k, row[k], ‘, ‘.join(map(unicode, v))

If a line doesn’t validate the script prints the validation errors and moves to the next line. If your data has columns you want to ignore then just name them in the `column_map` – the form class will ignore extra keys in the dictionary.

[django]: http://www.djangoproject.com
[modelform]: http://docs.djangoproject.com/en/dev/topics/forms/modelforms/

Leave a Reply

Your email address will not be published. Required fields are marked *