简体   繁体   English

Django:使用输入选项创建多选表单

[英]Django: create multi choice form with input option

I wanted to ask if someone know how to make a selection in a form where one of the choices is to add input 我想询问是否有人知道如何在一个选项中添加输入的表单中进行选择

in my forms.py: 在我的forms.py中:

class InRes(forms.ModelForm):

    class Meta:
        model=Results

in my models.py: 在我的models.py中:

PORT_STATUS=(
    ('FTP','21'),
    ('HTTP','443,80'),
)

class Results(models.Model):
    status=models.CharField(max_length=5, choices=PORT_STATUS, default='HTTP')

i want to add and option to select one of the choices or entering my own input. 我想添加和选项选择其中一个选项或输入我自己的输入。 any ideas? 有任何想法吗?

Django forms are very picky when it comes to what is a valid choice, which is a good thing. 当谈到什么是有效的选择时,Django形式非常挑剔,这是一件好事。 It prevents malicious values from being passed in via manipulated POST data. 它可以防止恶意值通过操纵的POST数据传入。

As such, you won't be able to programmatically add a choice, for one, because your choices are a hard-coded tuple, and two, because whatever choice you add won't be part of the choices the form considers valid when clean is run, because the value wasn't there when the form was initialized. 因此,您将无法以编程方式为一个选项添加选项,因为您的选择是一个硬编码的元组,两个,因为您添加的任何选项都不会成为表单在clean时认为有效的选项的一部分运行,因为初始化表单时该值不存在。

Instead, consider making the choices a separate model, and provide a separate form field to add a record for that model, so that next time, the choice will be present. 相反,考虑将选择作为单独的模型,并提供单独的表单字段来为该模型添加记录,以便下次选择将存在。

Django forms can have a mixture of model and non-model fields, so use that to add the input field. Django表单可以混合使用模型和非模型字段,因此使用它来添加输入字段。 You could also control the visibility of the extra field via JavaScript. 您还可以通过JavaScript控制额外字段的可见性。 It's probably possible to combine all of this into a multi-widget for a custom field. 可能将所有这些组合成一个自定义字段的多小部件。

# theoretical code, not tested

class PortStatus(models.Model):
    status = models.CharField(max_length=100)

    def __unicode__(self):
        return self.status


# I prefer singular model names

class Result(models.Model):
    status = models.ForeignKey(PortStatus, blank=True)


class ResultsForm(forms.ModelForm):

    class Meta:
        model = Result

    extra_choice = forms.CharField(max_length=100, required=False)

    def __init__(self, *args, **kwargs):
        super(ResultsForm, self).__init__(*args, **kwargs)
        self.save_new_status = False

    def clean(self):
        cleaned_data = self.cleaned_data()
        status = cleaned_data.get('status')
        extra_choice = cleaned_data.get('extra_choice')

        if status and extra_choice:
            raise forms.ValidationError("Can't specify both")

        if not status and not extra_choice:
            raise forms.ValidationError('Make a selection or add status')

        if not status and extra_choice:
            # make sure extra_choice isn't already in choices
            if PostStatus.objects.filter(
                status__iexact=extra_choice).count() > 0:
                    raise forms.ValidationError('Status present, etc')
            else:
                self.save_new_status = True

        return cleaned_data

    def save(self, commit=True)
        instance = super(ResultsForm, self).save(commit=False)
        if self.save_new_status:
            new_status = PostStatus.objects.create(
                status=self.cleaned_data.get('extra_choice'))
            self.status = new_status
        if commit:
            instance.save()
        return instance

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM