Creating Django Oscar Initial Data Migration

I’m working on an online shop for our local hackerspace Coredump. To implement
it, we chose django-oscar because I already know how to deal with Django and
because it seems to be very customizeable.

In the docs
it is mentioned that every shop needs a product class and a fulfillment
partner. The proper way to implement that is to create a data migration.

The docs link to django-south though, the 3rd party database migration library
that has been superceded with Django’s own migration framework. So the
instructions are not 100% clear anymore. After some failed attempts, I worked
out how to properly create data migrations for Oscar.

1. Create a Django app

First of all, you need a django app to contain your data migrations. If you
haven’t created one yet, do it now:

$ ./manage.py startapp data

Then add it to INSTALLED_APPS in your settings.py.

I’d recommend to also create an initial migration, so that your data
migration isn’t the first one.

$ ./manage.py makemigrations --empty data

2. Create a data migration

Now you can create an empty data migration. Django’s migration framework doesn’t
differentiate between data migrations and schema migrations anymore, so you can
just use the --empty argument:

$ ./manage.py makemigrations --empty data

3. Find dependencies

It is recommended to create initial instances of the following models:

  • Product Category
  • Product Class
  • Fulfillment Partner
  • Partner Address

Additionally, if you don’t import countries with ./manage.py
oscar_populate_countries
, you need to create a Country instance.

In order to create model instances for other apps, you need them as
dependencies. All these models are created in the corresponding initial
migration, therefore you can use the following dependency list:

dependencies = [
    # Your own app
    ('data', '0001_initial'),
    # Oscar apps
    ('catalogue', '0001_initial'),
    ('partner', '0001_initial'),
    ('address', '0001_initial'),
]

4. Write RunPython functions

For each of these model types we’ll create a function that can be run with the
migrations.RunPython operation. Here’s the example for the country:

def create_countries(apps, schema_editor):
    Country = apps.get_model("address", "Country")
    Country.objects.create(
        iso_3166_1_a2='CH',
        iso_3166_1_a3='CHE',
        iso_3166_1_numeric='756',
        printable_name='Schweiz',
        name='Schweiz',
        display_order=0,
        is_shipping_country=True)

It’s important that you use address as app label and not
oscar.apps.address or oscar.apps.address.models.

Add matching functions for all other data types.

5. Example

That’s it. If you want to see an example of such a data migration, see
https://github.com/coredump-ch/shop/blob/master/apps/data/migrations/0002_product_types_and_partners.py.