You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django中同配置字段仅其一未显示空白验证消息的问题求助

Django字段验证异常:to字段未显示空白验证消息

问题描述

两个配置完全相同的CharField字段(to和reason),使用同一类型Widget,但提交空白内容时,to字段未显示空白验证消息,reason字段正常显示。

相关代码

Model

class MagangLetter(models.Model):
    to=models.CharField(max_length=255)
    reason=models.CharField(max_length=255)
    start_date=models.DateField()
    end_date=models.DateField()

Form

class MagangLetterForm(forms.ModelForm):
    class Meta:
        model=MagangLetter
        fields=['to','reason','start_date','end_date']
        widgets={
            'to':forms.Textarea(attrs={'class':'form-control','rows':'3','placeholder':'''#example'''}),
            'reason':forms.Textarea(attrs={'class':'form-control','rows':'3','placeholder':'''#example'''}),
            'start_date':forms.DateInput(attrs={'class':'form-control','type':'date'}),
            'end_date':forms.DateInput(attrs={'class':'form-control','type':'date'})
        }

View

class CreateLetterMagang(CreateView):
    model=MagangLetter
    form_class=MagangLetterForm
    template_name_suffix="_create_form"
    def get_context_data(self, **kwargs):
        context=super().get_context_data(**kwargs)
        form:MagangLetter=context['form']
        file_template=Template(services.letter.get_html_template('magang.docx'))
        date=datetime.datetime.now()
        day=settings.MONTHS[date.strftime('%m')]
        file_context=Context({
            'letter_number' : '........',
            'date_submitted' : f'{date:%d} {day} {date:%Y}',
            'to': form['to'],
            'name': self.request.user.get_full_name(),
            'nim': self.request.user.detail.id_number,
            'reason':form['reason'],
            'start_date': form['start_date'],
            'end_date': form['end_date'],
            'nip':'.............',
            'dosen':'...............',
            'sign': ''
        })
        html=file_template.render(file_context)
        soup = BeautifulSoup(html, 'html.parser')
        date_submit=soup.find(string=re.compile("Yogyakarta,"))
        p=soup.find(string=re.compile("#test"))
        date_submit.parent.parent['style']='width:15rem;'
        p.parent['class']='p-0'
        p=soup.find(string=re.compile("#test"))
        p.parent['class']='p-0'
        p=soup.find(string=re.compile("#test"))
        p.parent['class']='p-0'
        table=(p.next_element.next_element.next_element)
        table['class'].append('text-center ms-auto')
        table['style']='width:fit-content'
        date_forms=soup.find_all(type='date')
        for date_form in date_forms:
            date_form['class'].append('w-25')
            date_form['style']='min-width:fit-content;'
        context['docx']=soup.prettify()
        return context

Template

{% block body %}
<div class="row content d-block overflow-auto">
    <div class="card p-3" style="width:40rem;">
        <form method='post'>
            {% csrf_token %}
            {{docx|safe}}
            <input type='submit' class='btn btn-primary' value='Buat Surat'></input>
        </form>
    </div>
</div>
{% endblock body %}

问题原因

  1. 表单验证时机错误:在get_context_data中提前访问form['to']字段,此时表单未完成验证流程,错误信息无法绑定到字段上。
  2. DOM元素模糊修改:多次通过#test字符串匹配元素并修改父类属性,误操作了to字段对应的错误提示容器,导致验证消息无法渲染。

解决方案

方案1:调整验证触发+精准定位DOM

修改View的get_context_data方法,确保POST请求时先触发表单验证,同时替换模糊匹配为精准定位字段元素:

class CreateLetterMagang(CreateView):
    model=MagangLetter
    form_class=MagangLetterForm
    template_name_suffix="_create_form"

    def get_context_data(self, **kwargs):
        context=super().get_context_data(**kwargs)
        form = context['form']
        
        # POST请求先触发验证,绑定错误信息
        if self.request.method == 'POST':
            form.is_valid()

        file_template=Template(services.letter.get_html_template('magang.docx'))
        date=datetime.datetime.now()
        day=settings.MONTHS[date.strftime('%m')]
        file_context=Context({
            'letter_number' : '........',
            'date_submitted' : f'{date:%d} {day} {date:%Y}',
            'to': form['to'],
            'name': self.request.user.get_full_name(),
            'nim': self.request.user.detail.id_number,
            'reason':form['reason'],
            'start_date': form['start_date'],
            'end_date': form['end_date'],
            'nip':'.............',
            'dosen':'...............',
            'sign': ''
        })
        html=file_template.render(file_context)
        soup = BeautifulSoup(html, 'html.parser')
        
        date_submit=soup.find(string=re.compile("Yogyakarta,"))
        date_submit.parent.parent['style']='width:15rem;'
        
        # 精准定位to字段容器
        to_field = soup.find('textarea', {'name': 'to'})
        if to_field:
            to_field.parent['class'] = 'p-0'
        
        # 精准定位reason字段容器及后续表格
        reason_field = soup.find('textarea', {'name': 'reason'})
        if reason_field:
            reason_field.parent['class'] = 'p-0'
            table=(reason_field.next_element.next_element.next_element)
            table['class'].append('text-center ms-auto')
            table['style']='width:fit-content'
        
        date_forms=soup.find_all(type='date')
        for date_form in date_forms:
            date_form['class'].append('w-25')
            date_form['style']='min-width:fit-content;'
        
        context['docx']=soup.prettify()
        return context

方案2:模板预留错误信息位置

检查docx模板,在to字段的textarea下方添加{{ form.to.errors }}占位,确保验证错误信息能被正确渲染到对应位置。

内容的提问来源于stack exchange,提问作者Fikra Laksana Putra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 15:15:46