Opened 13 years ago
Closed 12 years ago
#19364 closed Bug (invalid)
Wrong exception raised at django/db/models/fields/related.py:343? (DoesNotExist instead of AttributeError)
| Reported by: | Owned by: | ||
|---|---|---|---|
| Component: | Documentation | Version: | 1.4 |
| Severity: | Normal | Keywords: | DoesNotExist, django.db, getattr, |
| Cc: | lbragues | Triage Stage: | Accepted |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
My problem is at the admin models when calling a getattr from the save_module function using the object being saved, instead of returning the default value it raises a DoesNotExist exception, failing the python manual specification for getattr.
I'm wondering if the exception thrown shouldn't be AttributeError instead of DoesNotExist...
If I make a getattr call to that object and that exception is thrown my program will exit instead of being catched by the getattr method and the default value returned.
Reproducing:
models.py
class GroupProperty(models.Model):
CHOICES = (
('disk_quota','Disk Quota'),
('n_backups','Number of Backups'),
)
group = models.ForeignKey(Group)
key = models.CharField(max_length=200,choices=CHOICES)
value = models.CharField(max_length=200)
start = models.DateTimeField()
end = models.DateTimeField()
description = models.TextField()
author = models.ForeignKey(User)
edit = models.DateTimeField(default=datetime.now())
creation = models.DateTimeField(default=datetime.now())
# na alteracao actualiza data
def save(self):
self.edit = datetime.now()
super(GroupProperty, self).save()
class Meta:
verbose_name_plural = "Group Properties"
admin.py
class GroupPropertyAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['group','key','value','start','end',"description"]}),
('Auto generated fields', {'fields':['author','edit','creation']})
]
list_display = ('group', 'key','value','start','end')
readonly_fields = ('edit','author','creation')
list_filter = ['key','group']
search_fields = ['key','value','group','description']
ordering = ('-creation',)
def save_model(self, request, obj, form, change):
#Error here
if getattr(obj, 'author', 'None') is 'None':
obj.author = request.user
obj.save()
admin.site.register(GroupProperty, GroupPropertyAdmin)
Django stacktrace:
Environment:
Request Method: POST
Request URL: http://localhost:8080/admin/core/groupproperty/add/
Django Version: 1.4.2
Python Version: 2.7.3
Installed Applications:
('django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admin',
'*****.core')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware')
Traceback:
File "/usr/local/lib/python2.7/dist-packages/Django-1.4.2-py2.7.egg/django/core/handlers/base.py" in get_response
111. response = callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python2.7/dist-packages/Django-1.4.2-py2.7.egg/django/contrib/admin/options.py" in wrapper
366. return self.admin_site.admin_view(view)(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/Django-1.4.2-py2.7.egg/django/utils/decorators.py" in _wrapped_view
91. response = view_func(request, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/Django-1.4.2-py2.7.egg/django/views/decorators/cache.py" in _wrapped_view_func
89. response = view_func(request, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/Django-1.4.2-py2.7.egg/django/contrib/admin/sites.py" in inner
196. return view(request, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/Django-1.4.2-py2.7.egg/django/utils/decorators.py" in _wrapper
25. return bound_func(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/Django-1.4.2-py2.7.egg/django/utils/decorators.py" in _wrapped_view
91. response = view_func(request, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/Django-1.4.2-py2.7.egg/django/utils/decorators.py" in bound_func
21. return func(self, *args2, **kwargs2)
File "/usr/local/lib/python2.7/dist-packages/Django-1.4.2-py2.7.egg/django/db/transaction.py" in inner
209. return func(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/Django-1.4.2-py2.7.egg/django/contrib/admin/options.py" in add_view
955. self.save_model(request, new_object, form, False)
File "/home/someone/folder/to/project/****/core/admin.py" in save_model
36. if getattr(obj, 'author', 'None') is 'None':
File "/usr/local/lib/python2.7/dist-packages/Django-1.4.2-py2.7.egg/django/db/models/fields/related.py" in __get__
343. raise self.field.rel.to.DoesNotExist
Exception Type: DoesNotExist at /admin/core/groupproperty/add/
Exception Value:
Change History (9)
comment:1 by , 13 years ago
| Owner: | changed from to |
|---|
comment:2 by , 13 years ago
| Cc: | added |
|---|
comment:3 by , 13 years ago
| Component: | Database layer (models, ORM) → Documentation |
|---|---|
| Triage Stage: | Unreviewed → Accepted |
comment:4 by , 13 years ago
Then by throwing DoesNotExist we can't simply do a getattr call to check if the attribute exists in the db and if it has a value assigned, since DoesNotExists isn't catched by getattr.
It goes a little bit against what you expect python to do from reading the python docs http://docs.python.org/3/library/functions.html#getattr (docs v2 is equal).
And also if you do a dir(obj) the output shows that the object as a property with the name you are trying to get, so it can be a little confusing at first...
So the solution I adopted to do this is to try...except:
try:
#do something with object
except DosNotExist:
#do something on exception
comment:5 by , 13 years ago
| Has patch: | unset |
|---|
comment:6 by , 13 years ago
@akaariai, is the example with the text "p2 doesn't have an associated restaurant" what you're looking for?
https://docs.djangoproject.com/en/dev/topics/db/examples/one_to_one/
comment:7 by , 13 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
comment:8 by , 13 years ago
| Owner: | removed |
|---|---|
| Status: | assigned → new |
comment:9 by , 12 years ago
| Resolution: | → invalid |
|---|---|
| Status: | new → closed |
The
DoesNotExistis how relations work in Django. The attribute isn't missing. Getting the value for the attribute doesn't succeed as nothing exists for that attribute in the DB. HenceDoesNotExist.For some reason I can't find the this from the documentation. Seems somewhat surprising if this isn't documented...
I am leaving this open so that we can confirm that this is documented somewhere.