【问题标题】:Validation of an inline formset conditional to the value of a field from the parent form根据父表单中的字段值验证内联表单集
【发布时间】:2021-06-26 01:34:11
【问题描述】:

我想在 django 内联表单集 (form_date_event) 中使用自定义验证,以便根据父 (form_event) 表单上的一个值获得不同的验证。

具体来说,如果form_event 的类型是“录音发布”,我希望form_date_event 内联表单集接受一个空场地。我怎样才能做到这一点?下面的type = cleaned_data.get('type') 不起作用,我想是因为它获取了表单集的clean data,而不是父表单。

models.py:


class Venue(models.Model):
    venue_name = models.CharField(max_length=50)


class Event(models.Model):

    EV_TYPE = (
        ('performance', 'performance'),
        ('recording release', 'recording release'),
        ('other', 'other'),
    )
    title = models.CharField(max_length=200)
    type = models.CharField(max_length=20, choices=EV_TYPE, default="performance")


class dateEvent(models.Model):

    venue = models.ForeignKey(Venue, on_delete=models.CASCADE,null=True,blank=True)
    event = models.ForeignKey(Event, on_delete=models.CASCADE)
    start_date_time = models.DateTimeField(auto_now=False, auto_now_add=False)

forms.py:

class EventForm(forms.ModelForm):

    class Meta:
        model = Event
        fields = [
            'type',
            'title',
        ]

views.py:

class BaseDateEventFormSet(BaseInlineFormSet):
    def clean(self):
        cleaned_data = super().clean()
        type = cleaned_data.get('type')

        if type == 'recording release':
            self.add_error('repertoire', _("This field is required"))

        return cleaned_data


def event_edit_view(request, id):
    event = get_object_or_404(Event, id=id)
    active_user = request.user
    form_event = EventForm(request.POST or None, instance=event)
    DateEventFormSet = inlineformset_factory(Event, dateEvent, extra=5, can_delete=True, fields=('event', 'start_date_time', 'venue', 'link', 'link_description'),
    form_date_event = DateEventFormSet(request.POST or None, instance=Event.objects.get(id=id), prefix="dateEvent", queryset=dateEvent.objects.filter(event__id=id))


    context = {
        'event': event,
        'id': event.id,
        'form_event': form_event,
        'form_date_event': form_date_event,

        }

    if request.method == "POST":

        if form_event.is_valid() and request.POST['action'] == 'submit':
            if form_date_event.is_valid():

                flag=False
                evt_type = form_event.cleaned_data.get('type')
                for form in form_date_event:
                    print(form.cleaned_data.get('venue'))
                    if form.cleaned_data.get('venue') is None and evt_type !="recording release":
                        flag = True
                        break
                if flag:
                    messages.error(request,'Venue can be blank only for recording release events')
                    return render(request, "events/event-edit.html", context)
                else:
                    form_event.save()
                    form_date_event.save()
                    return redirect('my-events')
            else:
                raise forms.ValidationError(form_date_event.errors)

        elif form_event.is_valid() and form_date_event.is_valid() and request.POST['action'] == 'update':
            form_event.save()
            form_date_event.save()


        else:
            raise forms.ValidationError([form_event.errors, form_date_event.errors])

    return render(request, "events/event-edit.html", context)

【问题讨论】:

  • 接受空场地是什么意思?你是说None
  • 我的意思是用户只填写/提交start_date 并保持venue 字段不变。
  • 这必须在 view 中完成,因为您想使用两个表单来执行验证。
  • @Neeraj 这确实是我想要做的。正如您从我的问题中看到的那样,我说视图中的type = cleaned_data.get('type') 并没有做到这一点。我需要从其他表单中获取type。怎么样?
  • 代码必须写在 event_edit_view() 函数中

标签: django django-views django-forms


【解决方案1】:

dateEvent模型修改场地字段,venue = models.ForeignKey(Venue, on_delete=models.CASCADE,null=True,blank=True)

在 event_edit_view() 函数中,添加以下代码行

if form_date_event.is_valid() and form_event.is_valid()
    flag=False
    evt_type = form_event.cleaned_data.get('type')
    for form in form_date_event:
        if form.cleaned_data.get('venue') is None and evt_type !="recording release":
            flag = True
            break
    if flag:
        messages.error(request,'Venue can be blank only for recording release events')
        return render(request,myhtml.html,{'formset':form_date_event,'form':form_event})
    else:
        form_event.save()
        form_date_event.save()

【讨论】:

  • 谢谢。不幸的是,它没有按预期工作。我有一个要保存的录音版本,除了场地之外的所有字段都已填满,每次我点击保存按钮时,Django 都会将我重定向到“事件编辑”页面,但没有显示任何错误。
  • PS:我的模板中有 form_event.errors 和 form_date_event.errors。
  • 您是否修改了 dateEvent 中的“地点”字段?,所有其他事件类型都已保存?你也可以用“地点”保存“录音发布”吗?
  • 我忘了编辑模型,我的错。好的,所以,我可以保存有或没有场地的表演(这不是我想要的:我想要一个强制的表演场地),而我现在可以保存没有场地的录音(也就是说,我希望这是仅用于录音)。
  • 当您将其留空时,您能否在视图中打印 form.cleaned_data.get('venue') 和 form_event.cleaned_data.get('type') 并告诉我要打印什么。应该在“if”条件下检查该值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-15
  • 1970-01-01
  • 2011-09-17
  • 1970-01-01
  • 2021-11-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多