Opened 9 years ago

Closed 8 years ago

Last modified 8 years ago

#25292 closed Bug (fixed)

"'str' object has no attribute '_meta'" crash in ManyToManyField.through_fields check

Reported by: thbarrons Owned by: nobody
Component: Core (System checks) Version: 1.8
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: yes UI/UX: no

Description

version 1.8 doesn't handle an error properly in ManyToManyField.through_fields and gives useless feedback when performing system checks

I made a typo in defining a many to many through field in a model. See below. In my ManyToManyField.through_field for "Stage" I have "StageCatgeory" which is not correct the e and g are backwards.

See the stack trace below when running in v 1.8.4. it provides this useless info... AttributeError: 'str' object has no attribute '_meta'.

It wasn't until I tried running my app in 1.7.10, stack trace also below, that I got useful feedback on the problem and was able to solve it. Field specifies a many-to-many relation through model 'StageCatgeory', which has not been installed.

This seems like a bug that 1.7 handled it and 1.8 did not.

class Stage(models.Model):
    stage_id = models.AutoField(primary_key=True)
    categories = models.ManyToManyField('Category', through='StageCatgeory', related_name="stage_category")

class StageCategory(models.Model):
    stage = models.ForeignKey('Stage', db_column='stage_id')
    category = models.ForeignKey('Category',  db_column='category_id')

class Category(models.Model):
    category_id = models.AutoField(primary_key=True)
    stage = models.ManyToManyField('Stage', through='StageCategory', related_name="stage_category")
Django version 1.8.4, using settings 'my.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Performing system checks...

Unhandled exception in thread started by <function check_errors.<locals>.wrapper at 0x102cbad90>
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/django/utils/autoreload.py", line 225, in wrapper
    fn(*args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/django/core/management/commands/runserver.py", line 110, in inner_run
    self.validate(display_num_errors=True)
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/django/core/management/base.py", line 468, in validate
    return self.check(app_configs=app_configs, display_num_errors=display_num_errors)
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/django/core/management/base.py", line 481, in check
    include_deployment_checks=include_deployment_checks,
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/django/core/checks/registry.py", line 72, in run_checks
    new_errors = check(app_configs=app_configs)
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/django/core/checks/model_checks.py", line 28, in check_all_models
    errors.extend(model.check(**kwargs))
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/django/db/models/base.py", line 1207, in check
    errors.extend(cls._check_long_column_names())
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/django/db/models/base.py", line 1648, in _check_long_column_names
    for m2m in f.rel.through._meta.local_fields:
AttributeError: 'str' object has no attribute '_meta'
Django version 1.7.10, using settings 'my.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Performing system checks...

Unhandled exception in thread started by <function wrapper at 0x103de3cf8>
Traceback (most recent call last):
  File "/Users/me/virtualEnvs/myV2.7/lib/python2.7/site-packages/django/utils/autoreload.py", line 222, in wrapper
    fn(*args, **kwargs)
  File "/Users/me/virtualEnvs/myV2.7/lib/python2.7/site-packages/django/core/management/commands/runserver.py", line 105, in inner_run
    self.validate(display_num_errors=True)
  File "/Users/me/virtualEnvs/myV2.7/lib/python2.7/site-packages/django/core/management/base.py", line 362, in validate
    return self.check(app_configs=app_configs, display_num_errors=display_num_errors)
  File "/Users/me/virtualEnvs/myV2.7/lib/python2.7/site-packages/django/core/management/base.py", line 414, in check
    raise CommandError(msg)
django.core.management.base.CommandError: System check identified some issues:

ERRORS:
main.Stage.categories: (fields.E331) Field specifies a many-to-many relation through model 'StageCatgeory', which has not been installed.

System check identified 1 issue (0 silenced).

Attachments (1)

django-error.tar.gz (4.7 KB ) - added by mtomiyoshi 8 years ago.
Sample project

Download all attachments as: .zip

Change History (13)

comment:1 by Tim Graham, 9 years ago

Component: UncategorizedCore (System checks)
Type: Cleanup/optimizationBug

I couldn't reproduce the crash. Could you simplify your project to a minimal example?

comment:2 by Markus Holtermann, 9 years ago

I have yet to verify the ticket, but as a side note: I don't see a reason why you have the ManyToManyField on Category, as this is automatically added as a reverse relation by the ManyToManyField on Stage.

comment:3 by Tim Graham, 9 years ago

Resolution: needsinfo
Status: newclosed

comment:4 by Tim Graham, 9 years ago

Summary: doesn't handle an error properly in ManyToManyField.through_fields"'str' object has no attribute '_meta'" crash in ManyToManyField.through_fields check

in reply to:  description comment:5 by George Tantiras, 8 years ago

class Stage(models.Model):
    stage_id = models.AutoField(primary_key=True)

class Category(models.Model):
    category_id = models.AutoField(primary_key=True)
    stage = models.ManyToManyField('Stage', through='StageCategory', related_name="stage_category")

If we do not define the StageCategory table, the error is not understood at all:

$ ./manage.py runserver
Performing system checks...



Unhandled exception in thread started by <function check_errors.<locals>.wrapper at 0x7f3f16c930d0>
Traceback (most recent call last):
  File "/home/flyer/.virtualenvs/lived/lib/python3.4/site-packages/django/utils/autoreload.py", line 229, in wrapper
    fn(*args, **kwargs)
  File "/home/flyer/.virtualenvs/lived/lib/python3.4/site-packages/django/core/management/commands/runserver.py", line 114, in inner_run
    self.validate(display_num_errors=True)
  File "/home/flyer/.virtualenvs/lived/lib/python3.4/site-packages/django/core/management/base.py", line 469, in validate
    return self.check(app_configs=app_configs, display_num_errors=display_num_errors)
  File "/home/flyer/.virtualenvs/lived/lib/python3.4/site-packages/django/core/management/base.py", line 482, in check
    include_deployment_checks=include_deployment_checks,
  File "/home/flyer/.virtualenvs/lived/lib/python3.4/site-packages/django/core/checks/registry.py", line 72, in run_checks
    new_errors = check(app_configs=app_configs)
  File "/home/flyer/.virtualenvs/lived/lib/python3.4/site-packages/django/core/checks/model_checks.py", line 28, in check_all_models
    errors.extend(model.check(**kwargs))
  File "/home/flyer/.virtualenvs/lived/lib/python3.4/site-packages/django/db/models/base.py", line 1207, in check
    errors.extend(cls._check_long_column_names())
  File "/home/flyer/.virtualenvs/lived/lib/python3.4/site-packages/django/db/models/base.py", line 1648, in _check_long_column_names
    for m2m in f.rel.through._meta.local_fields:
AttributeError: 'str' object has no attribute '_meta'

comment:6 by Tim Graham, 8 years ago

Adding those models to a project, I still cannot reproduce a crash. Maybe you could provide a sample project?

comment:7 by Maxime Lorant, 8 years ago

I just had the same problem when modifying a M2M relation (adding extra data through intermediate model). Here is a translated example:

class Food(models.Model):
    stuff_to_use = models.ManyToManyField(Bar, through='Ingredient')
    class Meta:
        app_label = 'legacy_app'  # Bar and Ingredient does not have this app_label

... where Ingredient is a classic M2M model with 2 FKs and some extra data. The thing is Ingredient is not valid here and should be current_app.Ingredient. It seems Django does not raises errors when the model is not correctly resolved and treat the string passed as argument instead of the supposed model....

Hope it helps to find the issue.

comment:8 by Tim Graham, 8 years ago

A full sample project to reproduce would be useful.

by mtomiyoshi, 8 years ago

Attachment: django-error.tar.gz added

Sample project

comment:9 by mtomiyoshi, 8 years ago

Resolution: needsinfo
Status: closednew

I ran into this bug today using Django 1.9.7, I created a sample project to reproduce it.

It doesn't happen when you use SQLite, I'm not sure about other databases.

comment:10 by Tim Graham, 8 years ago

Easy pickings: set
Triage Stage: UnreviewedAccepted

Oh, right, the _check_long_column_names method doesn't do anything on SQLite so I couldn't reproduce there. We likely need to add a condition similar to what appears under the "Skip nonexistent models" comment in 21130ce1a9c4fcbfce4c614be9e5408b43092bf0.

comment:11 by Tim Graham <timograham@…>, 8 years ago

Resolution: fixed
Status: newclosed

In baff4dd:

Fixed #25292 -- Fixed crash in ManyToManyField.through_fields check.

comment:12 by Tim Graham <timograham@…>, 8 years ago

In f683bba6:

[1.10.x] Fixed #25292 -- Fixed crash in ManyToManyField.through_fields check.

Backport of baff4dd37dabfef1ff939513fa45124382b57bf8 from master

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