As reported here: http://groups.google.com/group/django-users/browse_thread/thread/da39ac4b1e5c1751# (and earlier but never recreated/isolated), under some circumstances a fieldsets definition in a ModelAdmin definition can cause the exception:
'str' object has no attribute '_default_manager'
Today's poster isolated the problem to mod_wsgi, and I was able to recreate with an example project he sent to me. There are two apps: catalogue and simplepromo (listed in that order in INSTALLED_APPS, reversing them didn't change anything). catalogue has a single model in models.py:
class Maker(models.Model):
dummy = models.CharField(blank=True, max_length=80)
def __unicode__(self):
return self.dummy
simplepromo (a simplified version of what Maciek sent me), also has a single model in models.py:
class SimplePromo(models.Model):
name = models.CharField(blank=False, max_length=250, help_text="Displayed in overlay tooltip")
slug = models.SlugField()
promo_maker = models.ForeignKey("catalogue.Maker", null=True, blank=False)
def __unicode__(self):
return self.name
and an admin.py file:
from django.contrib import admin
from simplepromo.models import *
class SimplePromoAdmin(admin.ModelAdmin):
prepopulated_fields = {'slug': ('name',)}
fieldsets = (
("Base", {
"fields": ["name","slug","promo_maker",],
}),
)
admin.site.register(SimplePromo, SimplePromoAdmin)
The call to admin.autodiscover() in urls.py is what generates the exception. If I remove the catch/transform to ImproperlyConfigured done by urlresolvers.py (ref #7524) I can get the actual traceback:
Environment:
Request Method: GET
Request URL: http://localhost/admin/
Django Version: 1.0-beta_1-SVN-8582
Python Version: 2.5.2
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.humanize',
'django.contrib.markup',
'django.contrib.sessions',
'django.contrib.sites',
'catalogue',
'simplepromo']
Installed Middleware:
('django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.middleware.doc.XViewMiddleware')
Traceback:
File "c:\u\kmt\django\trunk\django\core\handlers\base.py" in get_response
77. request.path_info)
File "c:/u/kmt/django/trunk\django\core\urlresolvers.py" in resolve
238. for pattern in self.urlconf_module.urlpatterns:
File "c:/u/kmt/django/trunk\django\core\urlresolvers.py" in _get_urlconf_module
257. self._urlconf_module = __import__(self.urlconf_name, {}, {}, [''])
File "c:/u/kmt/software/web/ppi-test\urls.py" in <module>
9. admin.autodiscover()
File "c:\u\kmt\django\trunk\django\contrib\admin\__init__.py" in autodiscover
19. __import__("%s.admin" % app)
File "c:/u/kmt/software/web/ppi-test\simplepromo\admin.py" in <module>
12. admin.site.register(SimplePromo, SimplePromoAdmin)
File "c:\u\kmt\django\trunk\django\contrib\admin\sites.py" in register
91. validate(admin_class, model)
File "c:\u\kmt\django\trunk\django\contrib\admin\validation.py" in validate
19. _validate_base(cls, model)
File "c:\u\kmt\django\trunk\django\contrib\admin\validation.py" in _validate_base
201. _check_form_field_existsw("fieldsets[%d][1]['fields']" % idx, field)
File "c:\u\kmt\django\trunk\django\contrib\admin\validation.py" in _check_form_field_existsw
162. return _check_form_field_exists(cls, model, opts, label, field)
File "c:\u\kmt\django\trunk\django\contrib\admin\validation.py" in _check_form_field_exists
282. fields = fields_for_model(model)
File "c:\u\kmt\django\trunk\django\forms\models.py" in fields_for_model
145. formfield = formfield_callback(f)
File "c:\u\kmt\django\trunk\django\forms\models.py" in <lambda>
124. def fields_for_model(model, fields=None, exclude=None, formfield_callback=lambda f: f.formfield()):
File "c:\u\kmt\django\trunk\django\db\models\fields\related.py" in formfield
726. defaults = {'form_class': forms.ModelChoiceField, 'queryset': self.rel.to._default_manager.complex_filter(self.rel.limit_choices_to)}
Exception Type: AttributeError at /admin/
Exception Value: 'str' object has no attribute '_default_manager'
I added a couple of local variables so I could see what's what and the local vars in that last routine are:
kwargs {}
self <django.db.models.fields.related.ForeignKey object at 0x01EC8390>
self_rel <django.db.models.fields.related.ManyToOneRel object at 0x01EC83B0>
self_rel_to 'catalogue.Maker'
Running the exact same app code under the development server plus putting a stop exception where the exception is generated under wsgi, I can see the local vars are different when running under the dev server:
kwargs {}
self <django.db.models.fields.related.ForeignKey object at 0x01067BB0>
self_rel <django.db.models.fields.related.ManyToOneRel object at 0x01067BD0>
self_rel_to <class 'catalogue.models.Maker'>
So somehow when running under the dev server (and anything other than wsgi, according to Maciek) self.rel.to has been transformed from a string to an actual class reference before this code is called. I haven't a clue how this happens or why it isn't happening when running under mod_wsgi, so that's about as far as I can go with this one. Hopefully someone else can shed some light?