Search code examples
python-3.xdjangodjango-modelsyamlmany-to-many

How do I structure YAML data for a many-to-many field (Python 3.9, Django 3)?


I'm using Python 3.9 and Django 3.0. I have defined the following models. The second has a many-to-many relationship with the first ...

class CoopType(models.Model):
    name = models.CharField(max_length=200, null=False)

    objects = CoopTypeManager()

    class Meta:
        # Creates a new unique constraint with the `name` field
        constraints = [models.UniqueConstraint(fields=['name'], name='coop_type_unq')]

...
class Coop(models.Model):
    objects = CoopManager()
    name = models.CharField(max_length=250, null=False)
    types = models.ManyToManyField(CoopType, blank=False)
    addresses = models.ManyToManyField(Address)
    enabled = models.BooleanField(default=True, null=False)
    phone = models.ForeignKey(ContactMethod, on_delete=models.CASCADE, null=True, related_name='contact_phone')
    email = models.ForeignKey(ContactMethod, on_delete=models.CASCADE, null=True, related_name='contact_email')
    web_site = models.TextField()

For the child entity, I have defined this "get_by_natural_key" method (the name field) ...

class CoopTypeManager(models.Manager):

    def get_by_natural_key(self, name):
        return self.get_or_create(name=name)[0]

How do I structure my YAML so that I can create a Coop with multiple types? This YAML works fine when there is only one type

  pk: 243
  fields:
    name: "Dill Pickle Food Co-op"
    types:
    - ['food coop']

but when I try and add more than one type, like so ...

  pk: 243
  fields:
    name: "Dill Pickle Food Co-op"
    types:
    - ['store', 'food coop']

I get this error ...

django.core.serializers.base.DeserializationError: Problem installing fixture '/tmp/seed_data.yaml': get_by_natural_key() takes 2 positional arguments but 3 were given: (directory.coop:pk=243) field_value was '['store', 'food coop']'

Solution

  • You do this with two items:

    pk: 243
      fields:
        name: "Dill Pickle Food Co-op"
        types:
        - ['food coop']
        - ['store']

    The list lists the natural keys of the types. You thus can not use two values here, since there is only the name.