首页 > 解决方案 > Django:ModelFormSet.is_valid() 抛出 ValidationError:ManagementForm 数据丢失或已被篡改

问题描述

我知道这个错误在 SO 上已经被问过很多次了,但是我读过的其他线程似乎都没有和我一样的情况,因为我并没有试图渲染表单集。我只是希望它仅用于发布的数据验证目的。这不是受支持的使用ModelFormSets 的方式吗?

Django 文档建议我可以这样做:

from django.forms import modelformset_factory
from django.shortcuts import render
from myapp.models import Author

def manage_authors(request):
    AuthorFormSet = modelformset_factory(Author, fields=('name', 'title'))
    if request.method == 'POST':
        formset = AuthorFormSet(request.POST, request.FILES)
        if formset.is_valid():
            formset.save()
            # do something.
    else:
        formset = AuthorFormSet()
    return render(request, 'manage_authors.html', {'formset': formset})

所以我一生都无法理解为什么下面的代码显然如此非法:

def add_player_to_teams(request):
    AddPlayerToTeamsFormSet = modelformset_factory(
        Team, fields=['players'])

        team_ids = post_data.getlist('team_ids')

        # Tried adding this, but the stupid thing **still** refuses to work!
        teams_init_data = {
            'teams-TOTAL_FORMS': len(team_ids),
            'teams-INITIAL_FORMS': '0'
        }

        post_data = post_data.copy()
        post_data.update(teams_init_data)

        teams_form_set = AddPlayerToTeamsFormSet(post_data,
            queryset=Team.objects.filter(unique_id__in=team_ids))

        status_dict = {
            'status': True,
            'errors': None
        }

        user = request.user

        if not teams_form_set.is_valid(): # Here's where it breaks
            status_dict['status'] = False
            status_dict['errors'] = teams_form_set.errors
        else:
            user.registration_step += 1
            user.save()

            for team in teams_form_set.save(commit=False):
                team.players.add(user)
                team.save()

            teams_form_set.save_m2m()

        return JsonResponse(status_dict)

更新:一位同事为我指出了正确的方向;prefix='teams'我在 formset 构造函数调用中丢失了。所以我更新的代码是:

teams_init_data = {
    'teams-TOTAL_FORMS': len(team_ids),
    'teams-INITIAL_FORMS': '0'
}

post_data = post_data.copy()
post_data.update(teams_init_data)

# Need to add prefix='teams' so that Django knows how to read the above
teams_form_set = AddPlayerToTeamsFormSet(post_data, prefix='teams',
    queryset=Team.objects.filter(unique_id__in=team_ids))

标签: pythondjangodjango-forms

解决方案


推荐阅读