我正在从 Django 1.3 升级到 1.5.5。以前所有的测试都有效,但现在这个失败了,我不知道为什么。我已经包含了堆栈跟踪和堆栈跟踪中出现的函数。有很多用于调试的日志语句,因此请注意。
Traceback (most recent call last):
File "/Users/athom09/Projects/openemory/openemoryEnv/lib/python2.7/site-packages/mock.py", line 1201, in patched
return func(*args, **keywargs)
File "/Users/athom09/Projects/openemory/openemory/../openemory/accounts/tests.py", line 878, in test_edit_profile
response = self.client.post(edit_profile_url, self.profile_post_data)
File "/Users/athom09/Projects/openemory/openemoryEnv/lib/python2.7/site-packages/django/test/client.py", line 463, in post
response = super(Client, self).post(path, data=data, content_type=content_type, **extra)
File "/Users/athom09/Projects/openemory/openemoryEnv/lib/python2.7/site-packages/django/test/client.py", line 297, in post
return self.request(**r)
File "/Users/athom09/Projects/openemory/openemoryEnv/lib/python2.7/site-packages/django/test/client.py", line 424, in request
six.reraise(*exc_info)
File "/Users/athom09/Projects/openemory/openemoryEnv/lib/python2.7/site-packages/django/core/handlers/base.py", line 115, in get_response
response = callback(request, *callback_args, **callback_kwargs)
File "/Users/athom09/Projects/openemory/openemory/../openemory/accounts/views.py", line 268, in public_profile
form.save(commit=False)
File "/Users/athom09/Projects/openemory/openemory/../openemory/accounts/forms.py", line 122, in save
return super(ProfileForm, self).save(*args, **kwargs)
File "/Users/athom09/Projects/openemory/openemory/../openemory/inlinemodelformsets.py", line 119, in save
fset.save()
File "/Users/athom09/Projects/openemory/openemoryEnv/lib/python2.7/site-packages/django/forms/models.py", line 514, in save
return self.save_existing_objects(commit) + self.save_new_objects(commit)
File "/Users/athom09/Projects/openemory/openemoryEnv/lib/python2.7/site-packages/django/forms/models.py", line 646, in save_new_objects
if self.can_delete and self._should_delete_form(form):
File "/Users/athom09/Projects/openemory/openemoryEnv/lib/python2.7/site-packages/django/forms/formsets.py", line 266, in _should_delete_form
return form.cleaned_data.get(DELETION_FIELD_NAME, False)
AttributeError: 'PositionForm' object has no attribute 'cleaned_data'
Accounts.test.py:
profile_post_data = {
'interests-MAX_NUM_FORMS': '',
'interests-INITIAL_FORMS': 0,
'interests-TOTAL_FORMS': 2,
'interests-0-interest': 'esoteric stuff',
'interests-0-DELETE': '',
'interests-1-interest': '',
'interests-1-DELETE': '',
# degrees, with formset management fields
'_DEGREES-MAX_NUM_FORMS': '',
'_DEGREES-INITIAL_FORMS': 0,
'_DEGREES-TOTAL_FORMS': 2,
'_DEGREES-0-name': 'BA',
'_DEGREES-0-institution': 'Somewhere Univ',
'_DEGREES-0-year': 1876,
'_DEGREES-1-name': 'MA',
'_DEGREES-1-institution': 'Elsewhere Institute',
# (degree year is optional)
# positions, with same
'_POSITIONS-MAX_NUM_FORMS': '',
'_POSITIONS-INITIAL_FORMS': 0,
'_POSITIONS-TOTAL_FORMS': 3,
'_POSITIONS-0-name': 'Big Cheese, Association of Curd Curators',
'_POSITIONS-1-name': 'Hole Editor, Journal of Swiss Studies',
#external links
'_EXTERNAL_LINKS-MAX_NUM_FORMS': '',
'_EXTERNAL_LINKS-INITIAL_FORMS': 0,
'_EXTERNAL_LINKS-TOTAL_FORMS': 2,
'_EXTERNAL_LINKS-0-title': 'Google',
'_EXTERNAL_LINKS-0-url': 'http://www.google.com',
'_EXTERNAL_LINKS-1-title': 'Yahoo!',
'_EXTERNAL_LINKS-1-url': 'http://www.yahoo.com',
# grants: TODO: not currently included in templates
# '_GRANTS-MAX_NUM_FORMS': '',
# '_GRANTS-INITIAL_FORMS': 0,
# '_GRANTS-TOTAL_FORMS': 3,
# '_GRANTS-0-name': 'Advanced sharpness research',
# '_GRANTS-0-grantor': 'Cheddar Institute',
# '_GRANTS-0-project_title': 'The effect of subject cheesiness on cheddar sharpness assessment',
# '_GRANTS-0-year': '1492',
# '_GRANTS-1-grantor': u'Soci\xb4t\xb4 Brie',
# '_GRANTS-1-project_title': 'A comprehensive analysis of yumminess',
'biography': 'Went to school *somewhere*, studied something else **elsewhere**.',
}
response = self.client.post(edit_profile_url, self.profile_post_data)
Accounts.views.py:
def public_profile(request, username):
'''Display public profile information and publications for the
requested author.
When requested via AJAX, returns HTML that can be displayed inside
a faculty dashboard tab.
'''
user, userprofile = _get_profile_user(username)
logger.info("AFTER USER")
form, interest_formset = None, None
context = {}
if request.method == 'POST':
logger.info("IN POST")
form = ProfileForm(request.POST, request.FILES, instance=userprofile)
logger.info("AFTER PROFILE FORM")
interest_formset = InterestFormSet(request.POST, prefix='interests')
logger.info("AFTER INTREST FORM")
if form.is_valid() and interest_formset.is_valid():
logger.info("IN VALID FORM")
logger.info("====================")
logger.info(dir(form))
logger.info("--------------------")
logger.info(dir(interest_formset))
logger.info("====================")
# save and redirect to profile
logger.info("B4 SAVE")
form.save(commit=False)
logger.info("AFTER SAVE")
new_interests = [f.cleaned_data.get('interest')
for f in interest_formset.forms
if f.cleaned_data.get('interest', '') and
not f.cleaned_data.get('DELETE', False)]
logger.info("AFTER GET INTRESTS")
userprofile.research_interests.set(*new_interests)
logger.info("AFTER SET INTRESTS")
# if a new photo file was posted, resize it
if 'photo' in request.FILES:
form.instance.resize_photo()
userprofile.save()
messages.success(request, 'Your profile was updated.')
# TODO: might want a different behavior when POSTed via ajax
logger.info("BEFORE POST REDIRECT")
return HttpResponseSeeOtherRedirect(reverse('accounts:dashboard-profile',
kwargs={'username': username}))
else:
logger.info("IN INVALID FORM")
context['invalid_form'] = True
if (request.user.has_perm("accounts.change_userprofile") or request.user == user) and not request.method == 'POST':
form = ProfileForm(instance=userprofile)
form.inlineformsets
interest_data = [{'interest': i}
for i in sorted(userprofile.research_interests.all())]
interest_formset = InterestFormSet(initial=interest_data, prefix='interests')
context.update({
'author': user,
'form': form,
'interest_formset': interest_formset,
})
if request.is_ajax():
# display a briefer version of the profile, for inclusion in faculty dash
template_name = 'accounts/snippets/profile-tab.html'
# for non-ajax requests, display full profile with documents
else:
# get articles where the user is the author
articles_query = userprofile.recent_articles_query()
paginated_articles, show_pages = paginate(request, articles_query)
url_params = request.GET.copy()
url_params.pop('page', None)
context.update({
'results': paginated_articles,
'show_pages': show_pages,
'url_params': url_params.urlencode(),
})
template_name = 'accounts/profile.html'
return render(request, template_name, context)
Accounts.forms.py:
def save(self, *args, **kwargs):
logger.info("INSIDE SAVE")
if hasattr(self, 'cleaned_data') and self.cleaned_data.get('delete_photo', False):
logger.info("INSIDE CLEAN IF")
# save=False because we're in the middle of save, and that would
# probably cause this to go recursive or the world to implode or
# something.
logger.info("BEFORE PHOTO DELETE")
self.instance.photo.delete(save=False)
logger.info("AFTER PHOTO DELETE")
logger.info("BEFORE SAVE RETURN")
内联模型formsets.py:
def save(self, *args, **kwargs):
logger.info("IN PSAVE")
instance = super(ModelForm, self).save(*args, **kwargs)
if hasattr(self._forms, 'inlines'):
for key, FormSet in self._forms.inlines.items():
fset = FormSet(self.data, self.files, prefix=self._get_formset_prefix(key),
instance=instance)
logger.info("BEFORE PSAVE FSET SAVE")
fset.save()
logger.info("BEFORE PSAVE RETURN")
return instance
return super(ProfileForm, self).save(*args, **kwargs)