0

我正在从 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)
4

1 回答 1

0

您需要在保存表单集之前对其进行验证。

            fset = FormSet(self.data, self.files, prefix=self._get_formset_prefix(key),
                           instance=instance)
            logger.info("BEFORE PSAVE FSET SAVE")
            if fset.is_valid():
                fset.save()
            else:
                // display form errors

当您知道导致表单集无法保存的错误时,您可以调整profile_post_data数据以确保它有效。

于 2013-11-25T07:26:59.560 回答