#21438 closed Bug (fixed)

Migrations do not detect many to many fields

Reported by: zaharid@… Owned by: andrewgodwin
Component: Migrations Version: master
Severity: Normal Keywords: manytomany foreignkey
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

When I add a manytomany field to an existing model, and then do a migration, the corresponding table does not get created. Sample error:

---------------------------------------------------------------------------
OperationalError                          Traceback (most recent call last)
<ipython-input-6-6970514bfc33> in <module>()
----> 1 c.save()

/usr/local/lib/python2.7/dist-packages/django/db/models/base.pyc in save(self, force_insert, force_update, using, update_fields)
    579 
    580         self.save_base(using=using, force_insert=force_insert,
--> 581                        force_update=force_update, update_fields=update_fields)
    582     save.alters_data = True
    583 

/usr/local/lib/python2.7/dist-packages/django/db/models/base.pyc in save_base(self, raw, force_insert, force_update, using, update_fields)
    616         if not meta.auto_created:
    617             signals.post_save.send(sender=origin, instance=self, created=(not updated),
--> 618                                    update_fields=update_fields, raw=raw, using=using)
    619 
    620     save_base.alters_data = True

/usr/local/lib/python2.7/dist-packages/django/dispatch/dispatcher.pyc in send(self, sender, **named)
    183 
    184         for receiver in self._live_receivers(sender):
--> 185             response = receiver(signal=self, sender=sender, **named)
    186             responses.append((receiver, response))
    187         return responses

/home/zah/project/instruments/utils.pyc in wrapper(sender, **kwargs)
     20         @wraps(func)
     21         def wrapper(sender, **kwargs):
---> 22             return func(kwargs.get('instance'))
     23         signal.connect(wrapper, sender=cls)
     24         return wrapper

/home/zah/project/instruments/models.py in post_save(self)
     33                 self.parameters.add(param)
     34     def post_save(self):
---> 35         self.get_params()
     36     def __unicode__(self):
     37         return self.name

/home/zah/project/instruments/models.py in get_params(self)
     31                 param = Parameter(name = param_name)
     32                 param.save()
---> 33                 self.parameters.add(param)
     34     def post_save(self):
     35         self.get_params()

/usr/local/lib/python2.7/dist-packages/django/db/models/fields/related.pyc in add(self, *objs)
    607         if rel.through._meta.auto_created:
    608             def add(self, *objs):
--> 609                 self._add_items(self.source_field_name, self.target_field_name, *objs)
    610 
    611                 # If this is a symmetrical m2m relation to self, add the mirror entry in the m2m table

/usr/local/lib/python2.7/dist-packages/django/db/models/fields/related.pyc in _add_items(self, source_field_name, target_field_name, *objs)
    683                     '%s__in' % target_field_name: new_ids,
    684                 })
--> 685                 new_ids = new_ids - set(vals)
    686 
    687                 if self.reverse or source_field_name == self.source_field_name:

/usr/local/lib/python2.7/dist-packages/django/db/models/query.pyc in __iter__(self)
    138                - Responsible for turning the rows into model objects.
    139         """
--> 140         self._fetch_all()
    141         return iter(self._result_cache)
    142 

/usr/local/lib/python2.7/dist-packages/django/db/models/query.pyc in _fetch_all(self)
    960     def _fetch_all(self):
    961         if self._result_cache is None:
--> 962             self._result_cache = list(self.iterator())
    963         if self._prefetch_related_lookups and not self._prefetch_done:
    964             self._prefetch_related_objects()

/usr/local/lib/python2.7/dist-packages/django/db/models/query.pyc in iterator(self)
   1182     def iterator(self):
   1183         if self.flat and len(self._fields) == 1:
-> 1184             for row in self.query.get_compiler(self.db).results_iter():
   1185                 yield row[0]
   1186         elif not self.query.extra_select and not self.query.aggregate_select:

/usr/local/lib/python2.7/dist-packages/django/db/models/sql/compiler.pyc in results_iter(self)
    672         fields = None
    673         has_aggregate_select = bool(self.query.aggregate_select)
--> 674         for rows in self.execute_sql(MULTI):
    675             for row in rows:
    676                 if has_aggregate_select:

/usr/local/lib/python2.7/dist-packages/django/db/models/sql/compiler.pyc in execute_sql(self, result_type)
    753 
    754         cursor = self.connection.cursor()
--> 755         cursor.execute(sql, params)
    756 
    757         if not result_type:

/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.pyc in execute(self, sql, params)
     75         start = time()
     76         try:
---> 77             return super(CursorDebugWrapper, self).execute(sql, params)
     78         finally:
     79             stop = time()

/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.pyc in execute(self, sql, params)
     59                 return self.cursor.execute(sql)
     60             else:
---> 61                 return self.cursor.execute(sql, params)
     62 
     63     def executemany(self, sql, param_list):

/usr/local/lib/python2.7/dist-packages/django/db/utils.pyc in __exit__(self, exc_type, exc_value, traceback)
     91                 if dj_exc_type not in (DataError, IntegrityError):
     92                     self.wrapper.errors_occurred = True
---> 93                 six.reraise(dj_exc_type, dj_exc_value, traceback)
     94 
     95     def __call__(self, func):

/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.pyc in execute(self, sql, params)
     59                 return self.cursor.execute(sql)
     60             else:
---> 61                 return self.cursor.execute(sql, params)
     62 
     63     def executemany(self, sql, param_list):

/usr/local/lib/python2.7/dist-packages/django/db/backends/sqlite3/base.pyc in execute(self, query, params)
    487             return Database.Cursor.execute(self, query)
    488         query = self.convert_query(query)
--> 489         return Database.Cursor.execute(self, query, params)
    490 
    491     def executemany(self, query, param_list):

Change History (3)

comment:1 Changed 21 months ago by timo

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Summary changed from Djando migrations do not track many to many fields to Migrations do not detect many to many fields
  • Triage Stage changed from Unreviewed to Accepted

I confirmed that after adding a ManyToManyField to an existing model and running makemigrations, no changes are detected.

comment:2 Changed 20 months ago by andrewgodwin

  • Owner set to andrewgodwin
  • Status changed from new to assigned

Probably an oversight on my part. I'll look into it.

comment:3 Changed 20 months ago by Andrew Godwin <andrew@…>

  • Resolution set to fixed
  • Status changed from assigned to closed

In 5e63977c0e5d0dff755817b86364a5c8882deaf7:

Fixed #21438: makemigrations now detects ManyToManyFields

Note: See TracTickets for help on using tickets.
Back to Top