0

我有一个具有以下自定义 clean() 方法的表单:

def clean(self):
        cleaned_data = self.cleaned_data
        event_date = cleaned_data.get("event_date")
        location = cleaned_data.get("location")

        if event_date and location:
            cleaned_data['relevance'] = True
        else:
            cleaned_data['relevance'] = False
            raise forms.ValidationError("You need to supply at least Event and Location information")

        return cleaned_data

我想向用户展示 ValidationError 以便他们修复错误。
但是,创建此表单的表单集设置了 extra=0,如下所示:

CodingFormSet = formset_factory(CodingForm, extra=0)
if request.method=='POST':
        
        [...]
        
        elif "coding_form_save" in request.POST:
            formset = CodingFormSet(request.POST, prefix="coding_form")

            process_form(formset, request, current_page, paginator)
            
            update_location_set(formset, coded_events, location_queryset)
            
            redirect_to = "?page=%s" % current_page
            return HttpResponseRedirect(redirect_to)

def process_form(formset, request, current_page, paginator):
if formset.is_valid():
    for form in formset.forms:
        form = form.cleaned_data
        
        if form["relevance"] == False:
            pass
        elif form["relevance"] == True:
            
            event_form = EventRecordForm()
        
            event = event_form.save(commit=False)
            event.article = paginator.page(current_page).object_list[0]
            event.coder = request.user
            event.last_updated = datetime.datetime.today()
            event.event_date = form["event_date"]
            event.location = form["location"]
            event.actors = form["actors"]
            event.num_participants = form["num_participants"]
            event.issue = form["issue"]
            event.side = form["side"]
            event.scope = form["scope"]
            event.part_violence = form["part_violence"]
            event.sec_engagement = form["sec_engagement"]
            event.save()
    
    ##### Add info on who worked on the article when
    history_form = ArticleHistoryForm()
    article_history = history_form.save(commit=False)
    article_history.article = paginator.page(current_page).object_list[0]
    article_history.coder = request.user
    article_history.last_updated = datetime.datetime.now()
    article_history.save()

有没有办法保持 extra=0 并且仍然显示用户验证错误?
更新:感谢@Alasdair,我现在可以通过仅在表单有效时重定向来显示验证错误。代码现在如下所示:

def assignment(request, pk):
"""View for each assignment"""
if request.user.is_authenticated():
    
    #### Get correct articles
    assignment = get_object_or_404(Assignment, pk=pk)
    country = assignment.country.cowcode
    start_date = assignment.start_date
    end_date = assignment.end_date
    articles = Article.objects.filter(cowcode=country).filter(pubdate__range=(start_date,end_date))
    
    #### Pagination ####
    paginator = Paginator(articles, 1)
    page = request.GET.get('page')
    try:
        articles = paginator.page(page)
    except PageNotAnInteger:
        articles = paginator.page(1)
    except EmptyPage:
        articles = paginator(page(paginator.num_pages))
    
    # Check if on first page and enable redirect
    if page is None:
        current_page = 1
    else:
        current_page = page
    redirect_to = "?page=%s" % current_page

    ##### Show already created events on the page
    current_article = paginator.page(current_page).object_list[0]
    EventFormSet = modelformset_factory(EventRecord, can_delete=True, exclude=('coder','article','url','last_updated'), extra=0)
    event_queryset = EventRecord.objects.filter(article__id=current_article.id).filter(coder=request.user.id)
    coded_events = EventFormSet(queryset=event_queryset, prefix="event_form")
    
    last_updated = ArticleHistory.objects.filter(coder=request.user.id).filter(article__id=current_article.id).order_by('-pk')[0]
    ##### Create Forms    
    CodingFormSet = formset_factory(CodingForm, extra=0)
    
    ###### Get correct locations
    location_queryset = Geonames.objects.filter(cowcode=country).order_by('name')
    
    if request.method=='POST':
        
    ##### Check if coder wants to go to next page or stay
        if "coding_form_next" in request.POST:
            formset = CodingFormSet(request.POST, prefix="coding_form")


            process_form(formset, request, current_page, paginator, next_article, coded_events, location_queryset)
            
            update_location_set(formset, coded_events, location_queryset)
        
            #current_page = int(current_page) + 1
            #redirect_to = "?page=%s" % current_page
            #return HttpResponseRedirect(redirect_to)
        
        elif "coding_form_save" in request.POST:
            formset = CodingFormSet(request.POST, prefix="coding_form")
            

            process_form(CodingFormSet, formset, request, current_page, paginator, next_article, coded_events, location_queryset)
            
            update_location_set(formset, coded_events, location_queryset)
            
            #redirect_to = "?page=%s" % current_page
            #return HttpResponseRedirect(redirect_to)
    
        elif 'add_event' in request.POST:
            
            cp = request.POST.copy()
            cp['coding_form-TOTAL_FORMS'] = int(cp['coding_form-TOTAL_FORMS'])+ 1
            formset = CodingFormSet(cp,prefix='coding_form')
                    
            update_location_set(formset, coded_events, location_queryset)
        elif 'save_changes' in request.POST:
            formset = CodingFormSet(prefix="coding_form")
            changed_events = EventFormSet(request.POST, prefix="event_form")
            instances = changed_events.save()
            
            update_location_set(formset, coded_events, location_queryset)
            
            history_form = ArticleHistoryForm()
            article_history = history_form.save(commit=False)
            article_history.article = paginator.page(current_page).object_list[0]
            article_history.coder = request.user
            article_history.last_updated = datetime.datetime.now()
            article_history.save()
            
            EventFormSet = modelformset_factory(EventRecord, can_delete=True, exclude=('coder','article','url','last_updated'), extra=0)
            event_queryset = EventRecord.objects.filter(article__id=current_article.id).filter(coder=request.user.id)
            coded_events = EventFormSet(queryset=event_queryset, prefix="event_form")
    else:
        formset = CodingFormSet(request.POST or None,prefix="coding_form")
        
        update_location_set(formset, coded_events, location_queryset)

else:
    print ERROR
return render(request, 'coding/assignment.html', 
{'articles':articles,'assignment':assignment,'formset':formset,'coded_events':coded_events,'last_updated':last_updated})

def process_form(CodingFormSet, formset, request, current_page, paginator, next_article, coded_events, location_queryset):
if formset.is_valid():
    for form in formset.forms:
        form = form.cleaned_data
        
        if form["relevance"] == False:
            pass
        elif form["relevance"] == True:
            
            event_form = EventRecordForm()
        
            event = event_form.save(commit=False)
            event.article = paginator.page(current_page).object_list[0]
            event.coder = request.user
            event.last_updated = datetime.datetime.today()
            event.event_date = form["event_date"]
            event.location = form["location"]
            event.actors = form["actors"]
            event.num_participants = form["num_participants"]
            event.issue = form["issue"]
            event.side = form["side"]
            event.scope = form["scope"]
            event.part_violence = form["part_violence"]
            event.sec_engagement = form["sec_engagement"]
            event.save()
    
    ##### Add info on who worked on the article when
    history_form = ArticleHistoryForm()
    article_history = history_form.save(commit=False)
    article_history.article = paginator.page(current_page).object_list[0]
    article_history.coder = request.user
    article_history.last_updated = datetime.datetime.now()
    article_history.save()
    
    
    redirect_to = "?page=%s" % current_page
    return HttpResponseRedirect(redirect_to)

然而,现在有什么不同,最好用三张图片来展示:
在旧代码中,敲击save编码器后会看到以下内容: 老办法

现在,在击中save编码器后看到:
在此处输入图像描述 这看起来他根本没有点击保存。

只有在save再次点击或重新加载页面后,他或她才会看到: 在此处输入图像描述

我想回到第一张图片,编码人员看到编码事件并且没有包含相同信息的新表单。请注意,他的发生是因为我移动了两行代码而没有做任何其他事情。
非常感谢任何帮助!

4

1 回答 1

1

我认为拥有extra=0与是否显示错误无关。

在处理表单集时,以下模式非常常见:

def my_view(request):
    if request.method == "POST"
        formset = MyFormSet(request.POST, prefix="coding_form")
        if formset.is_valid():
            do_something_with_formset()
            return HttpResponseRedirect("/success_url/")
    else:
        formset = MyFormSet(request.POST, prefix="coding_form")
    return render(request, "my_template.html", {'formset': formset}

当请求方法为 GET 时,将呈现一个空白表单集。当表单集无效时,表单集会被渲染,并会显示错误。我们仅在表单集有效时重定向。

在您的情况下,无论表单集是否有效,您总是在请求方法为 POST 时重定向。因此,当 formset 无效时,您将永远不会看到错误。

于 2013-07-27T15:32:50.083 回答