简体   繁体   中英

In Django how to add a placeholder to a form based on model charfield

I have a form:

class SideEffectForm(ModelForm):

    class Meta:
        model = SideEffect
        fields = ['se_name']

    def __init__(self, *args, p, **kwargs):
        super().__init__(*args, **kwargs)

        if p == 'antipsychotic':

            self.fields['se_name'].choices = [
                ("insomnia_and_agitation", "Insomnida and Agitation"),
                ("akathisia", "Akathisia"),
                ("dystonia", "Dystonia"),
            ]

That is based on this model:

class SideEffect(TimeStampedModel):

    SE_CHOICES = [
        ("insomnia_and_agitation", "Insomnida and Agitation"),
        ("akathisia", "Akathisia"),
        ("anticholinergic_effects", "Anticholinergic Side Effects")
    ]

    se_name = models.CharField("",max_length=200, choices=SE_CHOICES, blank=False)

    concern = models.IntegerField("",default=50)

    case = models.ForeignKey(Case, on_delete=models.CASCADE)

And this is the view:

class CaseView(LoginRequiredMixin, TemplateView):
    model = Case
    template_name = "se_balance/se_balance.html"
    
    def get(self, *args, **kwargs):
        p = self.request.GET.get("p", None)
        sideeffect_formset = SideeffectFormSet(queryset=SideEffect.objects.none(),
                                                form_kwargs={'p': p})


        return self.render_to_response(
            { "page_title": p.capitalize(),
              "sideeffect_formset": sideeffect_formset,
              "sideeffect_formsethelper": SideEffectFormSetSetHelper,
            }
        )

    def post(self, *args, **kwargs):
        p = self.request.GET.get("p", None)

        case_instance = Case(pharm_class_name=p)
        sideeffect_formset = SideeffectFormSet(data=self.request.POST, form_kwargs={'p': p})
        case_instance.save()

        if sideeffect_formset.is_valid():
            print('seform valid')
            sideeffect_name = sideeffect_formset.save(commit=False)
            for sideeffect in sideeffect_name:
                sideeffect.case = case_instance
                sideeffect.save()

            return redirect(
                reverse(
                    "results",
                    kwargs = {"case_id": case_instance.case_id}                )
            )

As it stands the form displays the first option. I would however like to have a place holder eg 'Please select a side effect'. I could do this by having it as one of the options (eg (None, 'This is the placeholder prompt') ) but would prefer not to as then would need to implement measures to stop the placeholder being saved as a valid user entry. I have tried a range of suggestions on the site but none have been suitable.

You stated:

I could do this by having it as one of the options (eg (None, 'This is the placeholder prompt')) but would prefer not to as then would need to implement measures to stop the placeholder being saved as a valid user entry.

No, that's not true, when we set (None, 'This is the placeholder prompt') there's no need to write the custom logic for not saving selected option in the database as valid user entry.

An Excerpt from the Django-doc about this issue.

Unless blank=False is set on the field along with a default then a label containing "---------" will be rendered with the select box. To override this behavior, add a tuple to choices containing None; eg (None, 'Your String For Display'). Alternatively, you can use an empty string instead of None where this makes sense - such as on a CharField.

Solution:

You can simply do this (None, 'please select the side effect') , but as stated while using CharField you should use ('', 'please select the side effect') this instead and also you've already set blank=False .

Try this:

class SideEffectForm(ModelForm):

    class Meta:
        model = SideEffect
        fields = ['se_name']

    def __init__(self, *args, p, **kwargs):
        super().__init__(*args, **kwargs)

        if p == 'antipsychotic':

            self.fields['se_name'].choices = [
                ('','Please select a side effect'),
                ("insomnia_and_agitation", "Insomnida and Agitation"),
                ("akathisia", "Akathisia"),
                ("dystonia", "Dystonia"),
            ]

After, doing this, see source code through Ctrl+U and you'll see below code of html:

<select ...> 
    <option value="" selected>please select the side effect</option>

    <option value="insomnia_and_agitation">Insomnida and Agitation</option>

    <option value="akathisia">Akathisia</option>

    <option value="dystonia">Dystonia</option>

</select>

And selected value doesn't save in database, so if you submit form with it, you'll see the error of required.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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