16

I need to create my own intermediate model.

class class1(models.Model):
    pass

class class2(models.Model):
    field1 = models.ManyToManyField(class1, through="class3")

class class3(models.Model):
    field1 = models.ForeignKey(class1)
    field2 = models.ForeignKey(class2)
    field3 = models.IntegerField()

    class Meta:
        auto_created = True

I use auto_created=True because in the following code, I had the error :

AttributeError: Cannot use add() on a ManyToManyField which specifies an intermediary model.

for m2m_field in self._meta.many_to_many:
    for m2m_link in getattr(self, m2m_field.get_attname()).all():
        getattr(to_object, m2m_field.get_attname()).add(m2m_link)

Now it works fine, but when I try to do a makemigration, django wants to remove my class3 (the intermediate class), and removing the through attribute in the field1 in class2.

What am I doing wrong ? Any solutions ?

Tks all.

ncopiy
  • 1,515
  • 14
  • 30
Raphael
  • 546
  • 2
  • 6
  • 25
  • I have the exactly same problem and here is my solution (ref: https://stackoverflow.com/questions/28693691/how-to-fake-migrations-for-not-to-create-a-specific-existing-intermediary-table) You can just run "makemigrations" to get auto generated scripts, then override there apply and unapply method so that when you run "migrate" command those operations won't be run. – link89 Jan 02 '18 at 01:35
  • In some cases you might be able to use [this trick](https://code.djangoproject.com/ticket/12203#comment:22) to get `auto_created` behavior without influencing your migrations. – djvg Jun 27 '20 at 20:07

1 Answers1

16

As far as I am aware, the auto_created attribute in the Meta class is undocumented, so you should avoid using it.

As the AttributeError says, it is not possible to use add() for a many to many field that uses an intermediary model. The correct fix is to create an instance of the intermediate model, instead of using add().

class3.objects.create(field_1=c1, field_2=c2, field_3=1).

See the docs on extra fields in many to many relationships for more info.

Alasdair
  • 298,606
  • 55
  • 578
  • 516
  • Yes, I found nothing about auto_created attribute in the django doc. Thanks. – Raphael Dec 21 '15 at 12:04
  • But, do you have any idea about why does django wants to delete my intermediate class ? – Raphael Dec 21 '15 at 14:34
  • I'm not familiar with `auto_created`, so I do not know why it would cause Django to want to delete your intermediate class. I assume that if you stop using it, then Django won't want to delete the intermediate class any more. – Alasdair Dec 21 '15 at 14:37
  • 3
    @Raphael In a migration, an `auto_created` model gets created by the `AddField` operation for the `ManyToManyField` -- it does not exist as a separate model, only as part of the model that defines the m2m field. Because the migration generator no longer sees the model in the model registry, it will try to delete it. You cannot (yet) change from a m2m with an explicit model to an auto-created model, or the other way around. – knbk Dec 21 '15 at 15:56