Repository: django-extensions/django-extensions

Issue:
shell_plus is broken for Models organized into models/app_mod.py files instead of single models.py (?)
I attempted to install `django_extensions` into my `INSTALLED_APPS` for the Sentry web application (https://github.com/getsentry/sentry).

Upon running `shell_plus` management command I receive this traceback:

```
(sentry)patrick@zeltennia:~/sentry$ python manage.py shell_plus --traceback
# Shell Plus Model Imports
Traceback (most recent call last):
  File "/.../virtualenv/lib/python2.7/site-packages/django/core/management/base.py", line 222, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "/.../virtualenv/lib/python2.7/site-packages/django/core/management/base.py", line 255, in execute
    output = self.handle(*args, **options)
  File "/.../virtualenv/lib/python2.7/site-packages/django/core/management/base.py", line 385, in handle
    return self.handle_noargs(**options)
  File "/.../virtualenv/lib/python2.7/site-packages/django_extensions/management/commands/shell_plus.py", line 161, in handle_noargs
    func()
  File "/.../virtualenv/lib/python2.7/site-packages/django_extensions/management/commands/shell_plus.py", line 124, in run_ipython
    imported_objects = import_objects(options, self.style)
  File "/.../virtualenv/lib/python2.7/site-packages/django_extensions/management/shells.py", line 146, in import_objects
    app_name = app_mod.split('.')[-2]
IndexError: list index out of range
```

This is the code block where the exception occurs (also seen here at https://github.com/django-extensions/django-extensions/blob/master/django_extensions/management/shells.py#L145):

```
for app_mod, models in sorted(six.iteritems(load_models)):                                                                
        app_name = app_mod.split('.')[-2]                           
        app_aliases = model_aliases.get(app_name, {})                   
        model_labels = [] 
```

I played with the offending `shells.py` file to get some useful information. Here is the output of `django.db.models.loading.get_apps()`:

```
<module 'django.contrib.admin.models' from '/.../virtualenv/lib/python2.7/site-packages/django/contrib/admin/models.pyc'>
<module 'django.contrib.auth.models' from '/.../virtualenv/lib/python2.7/site-packages/django/contrib/auth/models.pyc'>
<module 'django.contrib.contenttypes.models' from '/.../virtualenv/lib/python2.7/site-packages/django/contrib/contenttypes/models.pyc'>
<module 'django.contrib.messages.models' from '/.../virtualenv/lib/python2.7/site-packages/django/contrib/messages/models.pyc'>
<module 'django.contrib.sessions.models' from '/.../virtualenv/lib/python2.7/site-packages/django/contrib/sessions/models.pyc'>
<module 'django.contrib.sites.models' from '/.../virtualenv/lib/python2.7/site-packages/django/contrib/sites/models.pyc'>
<module 'django.contrib.staticfiles.models' from '/.../virtualenv/lib/python2.7/site-packages/django/contrib/staticfiles/models.pyc'>
<module 'captcha.models' from '/.../virtualenv/lib/python2.7/site-packages/captcha/models.pyc'>
<module 'crispy_forms.models' from '/.../virtualenv/lib/python2.7/site-packages/crispy_forms/models.pyc'>
<module 'djcelery.models' from '/.../virtualenv/lib/python2.7/site-packages/djcelery/models.pyc'>
<module 'kombu.transport.django.models' from '/.../virtualenv/lib/python2.7/site-packages/kombu/transport/django/models.pyc'>
<module 'raven.contrib.django.raven_compat.models' from '/.../virtualenv/lib/python2.7/site-packages/raven/contrib/django/raven_compat/models.pyc'>
<module 'rest_framework.models' from '/.../virtualenv/lib/python2.7/site-packages/rest_framework/models.pyc'>
<module 'sentry.models' from '/.../sentry.git/src/sentry/models/__init__.pyc'>
<module 'sentry.nodestore.models' from '/.../sentry.git/src/sentry/nodestore/models.pyc'>
<module 'sentry.search.models' from '/.../sentry.git/src/sentry/search/models.pyc'>
<module 'sentry.plugins.sentry_interface_types.models' from '/.../sentry.git/src/sentry/plugins/sentry_interface_types/models.pyc'>
<module 'sentry.plugins.sentry_mail.models' from '/.../sentry.git/src/sentry/plugins/sentry_mail/models.pyc'>
<module 'sentry.plugins.sentry_urls.models' from '/.../sentry.git/src/sentry/plugins/sentry_urls/models.pyc'>
<module 'sentry.plugins.sentry_useragents.models' from '/.../sentry.git/src/sentry/plugins/sentry_useragents/models.pyc'>
<module 'social_auth.models' from '/.../virtualenv/lib/python2.7/site-packages/social_auth/models.pyc'>
<module 'south.models' from '/.../virtualenv/lib/python2.7/site-packages/south/models.pyc'>
<module 'sudo.models' from '/.../virtualenv/lib/python2.7/site-packages/sudo/models.pyc'>
<module 'django_extensions.models' from '/.../virtualenv/lib/python2.7/site-packages/django_extensions/models.pyc'>
```

Finally, here is the output of `sorted(six.iteritems(load_models))` which is the iterable that gives the error:

```
[
    ('accessgroup', ['AccessGroup']),
    ('activity', ['Activity']),
    ('alert', ['Alert', 'AlertRelatedGroup']),
    ('django.contrib.admin.models', ['LogEntry']),
    ('django.contrib.auth.models', ['Permission', 'Group']),
    ('django.contrib.contenttypes.models', ['ContentType']),
    ('django.contrib.sessions.models', ['Session']),
    ('django.contrib.sites.models', ['Site']),
    ('djcelery.models', ['TaskMeta', 'TaskSetMeta', 'IntervalSchedule', 'CrontabSchedule', 'PeriodicTasks', 'PeriodicTask', 'WorkerState', 'TaskState']),
    ('event', ['Event']),
    ('eventmapping', ['EventMapping']),
    ('group', ['Group']),
    ('groupassignee', ['GroupAssignee']),
    ('groupbookmark', ['GroupBookmark']),
    ('groupmeta', ['GroupMeta']),
    ('grouprulestatus', ['GroupRuleStatus']),
    ('groupseen', ['GroupSeen']),
    ('grouptagkey', ['GroupTagKey']),
    ('grouptagvalue', ['GroupTagValue']),
    ('kombu.transport.django.models', ['Queue', 'Message']),
    ('lostpasswordhash', ['LostPasswordHash']),
    ('option', ['Option']),
    ('pendingteammember', ['PendingTeamMember']),
    ('project', ['Project']),
    ('projectkey', ['ProjectKey']),
    ('projectoption', ['ProjectOption']),
    ('rule', ['Rule']),
    ('sentry.nodestore.django.models', ['Node']),
    ('sentry.search.django.models', ['SearchDocument', 'SearchToken']),
    ('social_auth.db.django_models', ['UserSocialAuth', 'Nonce', 'Association']),
    ('south.models', ['MigrationHistory']),
    ('tagkey', ['TagKey']),
    ('tagvalue', ['TagValue']),
    ('team', ['Team']),
    ('teammember', ['TeamMember']),
    ('user', ['User']),
    ('useroption', ['UserOption'])
]
```

You will see that all of the offending model definitions occur with the Sentry web application project. A quick perusal of their source shows that all the models are segregated into one-model-per-one-file in a `models/` folder:
https://github.com/getsentry/sentry/tree/master/src/sentry/models

I added a simple `try/catch/continue` to keep working on my current project but hopefully someone else can take care of this easy pickings...



Discussion:

Resolving patch:
diff --git a/django_extensions/management/shells.py b/django_extensions/management/shells.py
--- a/django_extensions/management/shells.py
+++ b/django_extensions/management/shells.py
@@ -153,7 +153,11 @@ def import_objects(options, style):
     if not quiet_load:
         print(style.SQL_TABLE("# Shell Plus Model Imports"))
     for app_mod, models in sorted(six.iteritems(load_models)):
-        app_name = app_mod.split('.')[-2]
+        try:
+            app_name = app_mod.split('.')[-2]
+        except IndexError:
+            # Some weird model naming scheme like in Sentry.
+            app_name = app_mod
         app_aliases = model_aliases.get(app_name, {})
         model_labels = []
 


Test patch: