【问题标题】:Dynamic required fields according to user's selection in Django form根据用户在 Django 表单中选择的动态必填字段
【发布时间】:2021-04-14 14:10:26
【问题描述】:

我希望仅当用户选择并提交 type="performance" 时才需要两个字段(曲目和表演者)。这是我的模型:

class Event(models.Model):

    EV_TYPE = (
        ('performance', 'performance'),
        ('other', 'other'),
    )

    title = models.CharField(max_length=200)
    type = models.CharField(max_length=15, choices=EV_TYPE, default="performance")
    repertoire = models.ManyToManyField(Work, blank=True)
    performer = models.ManyToManyField(Profile, limit_choices_to={'role__type__contains': 'Performer'})

我的表格:

class EventForm(forms.ModelForm):

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

我的看法:

def event_create_view(request):

if request.method == 'POST':
    form_event = EventForm(
        request.POST,
        repertoire_required=(not (active_user.id == 17)), # if the user is NMS then the repertoire field is not compulsory
        initial={'submitted_by' : active_user.profile.id}
        )
    form_venue = AddVenueForm()
    form_profile = ProfileForm()
    form_work = WorkFromEventForm()

    if form_event.is_valid():

        this_event = form_event.save()
        return redirect('event-edit', id=this_event.id)

这是我尝试过的。在上面的“form_event.is_valid”中,我做到了:

    if form_event.is_valid():


        this_event = form_event.save(commit=False)
        if this_event['type'] == 'performance' and this_event['performer'] and this_event['repertoire']:
            this_event.save()
            return redirect('event-edit', id=this_event.id)

但这不起作用(我在提交时仍然收到“此字段是必需的”)。我怎样才能实现我想做的事情?

附录

这也不行:

if 

this_event['type'] == 'performance' and not this_event['performer'] or not this_event['repertoire']:
                messages.error(request, form_event.errors)
            else:
                this_event.save()
                

【问题讨论】:

    标签: django django-views django-forms


    【解决方案1】:

    您可以通过表单上的clean 方法来做到这一点。

    例如你可能会这样做;

    def clean(self):
        """
        Validate the form input
        """
        cleaned_data = super().clean()
        type = cleaned_data.get('type')
    
        if type == 'performance':
            repertoire = cleaned_data.get('repertoire')
            performer = cleaned_data.get('performer')
            if not repertoire:
                self.add_error('repertoire', _("This field is required"))
            if not performer:
                self.add_error('performer', _("This field is required"))
    
        return cleaned_data
    

    表单验证的文档在这里; https://docs.djangoproject.com/en/3.1/ref/forms/validation/

    【讨论】:

    • 太棒了,它有效,谢谢。我是否必须添加 blank=True, null=True 才能使上述代码正常工作?理想情况下,我一般不希望允许空的曲目和表演者(例如在管理界面等中)。
    • 是的,如果您的字段仅基于其他字段的值是必需的,您需要确保将它们设置为blank=True,以便 django 不会使它们成为必需。然后,您的工作就是确保表单验证在您的场景中成为必需。使用 javascript 显示/隐藏这样的字段通常是明智的,这样必填字段仅在需要时才显示。
    • 是的,这是我做的第一件事,我编写了一个 JavaScript,它既隐藏又取消了“必需”标志。当然这还不够,我还必须按照您的建议定义 clean() 方法。无论如何,现在一切正常。
    猜你喜欢
    • 2016-10-04
    • 1970-01-01
    • 2011-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 2012-08-06
    相关资源
    最近更新 更多