The official docs explain how to set up “natural keys” for easier writing of fixtures.

The things to remember are basically two:

  • setup a models.Manager (write the class with an appropriate get_by_natural_key method and instantiate it in the managed class)
  • the fields used for a natural key must be able to uniquely identify an object (typically that means a unique or unique_together constraint)

In this post I’ll show an example of a YAML fixture that works with a many-to-many relationship:

from django.db import models

class PippoManager(models.Manager):
    def get_by_natural_key(self, a, b):
        return self.get(name=a, surname=b)  

class Pippo(models.Model):
  objects = PippoManager()
  name = models.CharField()
  surname = models.CharField()

  class Meta:
    unique_together = (('name', 'surname'),)

class Pluto(models.Model):
  attr = models.CharField()
  pippos = models.ManyToManyField(Pippo)  

The fixtures are something like these

instances of Pippo

- model: app.Pippo
  pk: 1
    name: ehi
    surname: pera
- model: app.Pippo
  pk: 2
    name: ehi
    surname: mela

Instances of Pluto

- model: app.Pluto
  pk: 1
    attr: boh
    - - ehi
      - pera
    - - ehi
      - mela

The fixtures have to be loaded in the correct order: python loaddata pippo first and then python loaddata pluto. The awkwardness comes from the fact that each Pippo is serialized with a list of name+surname, but since we have a ManyToMany relationship you need a list of Pippos, hence the nested list.


comments powered by Disqus