如何在 Django 中修改 Bootstrap 4 表单验证信息呈现方式?

     2023-02-24     122

关键词:

【中文标题】如何在 Django 中修改 Bootstrap 4 表单验证信息呈现方式?【英文标题】:How to modify Bootstrap 4 form validation information presentation in Django? 【发布时间】:2021-03-11 05:08:08 【问题描述】:

我正在使用 Django 和 Bootstrap 4。我想自定义表单验证信息在我正在使用的模板中的显示方式。当当前模板发生错误时,无效的输入元素有红色轮廓,错误消息显示为弹出窗口。另外,正确输入的输入元素没有绿色轮廓,它们只是没有轮廓。

我想做以下事情:

发生错误时在字段下方显示错误消息 为输入正确的字段添加绿色轮廓

我尝试了多种解决方案,包括:

this tutorial this GitHub gist the Stack Overflow answers from this question

我的情况没有任何效果。

我当前的代码:

submit_job_listing.html(模板):

% extends "base.html" %
% block title % Submit a job % endblock %
% block nav_item_post_a_job %active% endblock nav_item_post_a_job %
% block head %
     job_listing_form.media.css 
% endblock %
% block content %

    <h1>Submit a job listing</h1>
    <div class="container">
      <form method="post" enctype="multipart/form-data">
          % csrf_token %
          <div class="row text-center">
            <h2> <b>Job listing information</b> </h2>
          </div>
          <br/>
          % for field in job_listing_form.visible_fields %
            <div class="form-group">
              <div class="row">
                <p> field.label_tag </p>
              </div>
              <div class="row">
                % if field.help_text %
                  <p class="form-text text-muted"> field.help_text </p>
                % endif %
              </div>
              <div class="row">
                 field 
              </div>
            </div>
          % endfor %
          <br/>
          <div class="row text-center">
            <h2> <b>Employer information</b> </h2>
          </div>
          <br/>
          % for field in employer_form.visible_fields %
            <div class="form-group">
              <div class="row">
                <p> field.label_tag </p>
              </div>
              <div class="row">
                % if field.help_text %
                  <p class="form-text text-muted"> field.help_text </p>
                % endif %
              </div>
              <div class="row">
                 field 
              </div>
            </div>
          % endfor %
        <input type="submit" value="Submit" class="btn btn-primary" />
      </form>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
       job_listing_form.media.js 
    </div>
% endblock %

views.py(相关部分):

def submitJobListing(request):
    if request.method == "POST":
        employer_form = EmployerForm(request.POST, request.FILES)
        job_listing_form = JobListingForm(request.POST, request.FILES)

        #check if employer with that name already exists
        employer_name = str(request.POST.get("name", ""))
        try:
            employer_with_the_same_name = Employer.objects.get(name=employer_name)
        except ObjectDoesNotExist:
            employer_with_the_same_name = None

        employer = None
        
        if (employer_with_the_same_name != None):
            employer = employer_with_the_same_name

        if employer == None and employer_form.is_valid() and job_listing_form.is_valid():
            employer = employer_form.save()

        job_listing = job_listing_form.save(commit=False)
        job_listing.employer = employer
        job_listing.save()
        job_listing_form.save_m2m()

        return SimpleTemplateResponse("employers/successful_job_listing_submission.html")

    else:
        employer_form = EmployerForm()
        job_listing_form = JobListingForm()

    context = 
        "employer_form": employer_form,
        "job_listing_form": job_listing_form,
    

    return render(request, 'employers/submit_job_listing.html', context)

forms.py(相关部分):

class EmployerForm(forms.ModelForm):
    name = forms.CharField(max_length=100)
    #location = forms.CharField(widget=LocationWidget)
    short_bio = forms.CharField(widget=forms.Textarea)
    website = forms.URLField()
    profile_picture = forms.ImageField()

    def __init__(self, *args, **kwargs):
        super(EmployerForm, self).__init__(*args, **kwargs)
        for visible in self.visible_fields():
            if isinstance(visible.field.widget, (forms.widgets.TextInput, forms.widgets.Textarea, forms.widgets.URLInput, LocationWidget)):
                visible.field.widget.attrs['class'] = 'form-control'
            if isinstance(visible.field.widget, forms.widgets.ClearableFileInput):
                visible.field.widget.attrs['class'] = 'form-control-file'

    class Meta:
        model = Employer
        fields = ["name", "short_bio", "website", "profile_picture"]

class JobListingForm(forms.ModelForm):
        job_title = forms.CharField(max_length=100, help_text="What's the job title?")
        job_description = forms.CharField(widget=forms.Textarea)
        job_requirements = forms.CharField(widget=forms.Textarea)
        what_we_offer = forms.CharField(widget=forms.Textarea)
        location = forms.CharField(widget=LocationWidget)
        remote = forms.BooleanField()
        job_application_url = forms.URLField()
        point_of_contact = forms.EmailField()
        categories = forms.ModelMultipleChoiceField(
                     queryset=Category.objects.all(),
                     widget=forms.CheckboxSelectMultiple,
                     required=True)

        def __init__(self, *args, **kwargs):
            super(JobListingForm, self).__init__(*args, **kwargs)
            for visible in self.visible_fields():
                if isinstance(visible.field.widget, (forms.widgets.TextInput, forms.widgets.Textarea, forms.widgets.URLInput, forms.widgets.EmailInput, LocationWidget)):
                    visible.field.widget.attrs['class'] = 'form-control'
                if isinstance(visible.field.widget, (forms.widgets.CheckboxInput, forms.widgets.CheckboxSelectMultiple)):
                    visible.field.widget.attrs['class'] = 'form-check'

        class Meta:
            model = JobListing
            fields = ["job_title", "job_description", "job_requirements", "what_we_offer", "location", "remote", "job_application_url", "categories", "point_of_contact"]

谁能告诉我怎样才能达到我想要的效果?

更新 1:

我尝试添加检查field.errors 的代码,但它不起作用。

这是submit_job_listing.html 模板文件:

% extends "base.html" %
% load widget_tweaks %
% block title % Submit a job % endblock %
% comment % https://***.com/questions/50028673/changing-active-class-in-bootstrap-navbar-not-staying-in-inherited-django-templa % endcomment %
% block nav_item_post_a_job %active% endblock nav_item_post_a_job %
% block head %
     job_listing_form.media.css 
    <!---
    <style>
        input, select width: 100%
    </style>
    --->
% endblock %
% block content %

% comment %
https://simpleisbetterthancomplex.com/article/2017/08/19/how-to-render-django-form-manually.html
% endcomment %

    <h1>Submit a job listing</h1>
    <div class="container">
      <form method="post" enctype="multipart/form-data">
          % csrf_token %
          <div class="row text-center">
            <h2> <b>Job listing information</b> </h2>
          </div>
          <br />
          <div class="row text-center">
            <p> <b>Note: Fields marked with an asterisk (*) are required</b> </p>
          </div>
          <br/>
          % for field in job_listing_form.visible_fields %
            <div class="form-group">
              <div class="row">
                <p> field.label_tag  field.field.required|yesno:"*," </p>
              </div>
              <div class="row">
                % if field.help_text %
                  <p class="form-text text-muted"> field.help_text </p>
                % endif %
              </div>
              <div class="row">
                 field 
                <p>  field.errors  </p>
                % if field.errors %
                  <div class="border-bottom-danger">
                       field.errors 
                  </div>
                % endif %
              </div>
            </div>
          % endfor %
          <br/>
          <div class="row text-center">
            <h2> <b>Employer information</b> </h2>
          </div>
          <br />
          <div class="row text-center">
            <p> <b>Note: Fields marked with an asterisk (*) are required</b> </p>
          </div>
          <br/>
          % for field in employer_form.visible_fields %
            <div class="form-group">
              <div class="row">
                <p> field.label_tag  field.field.required|yesno:"*," </p>
              </div>
              <div class="row">
                % if field.help_text %
                  <p class="form-text text-muted"> field.help_text </p>
                % endif %
              </div>
              <div class="row">
                 field 
              </div>
            </div>
          % endfor %
        <input type="submit" value="Submit" class="btn btn-primary" />
      </form>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
       job_listing_form.media.js 
    </div>
% endblock %

当我只单击提交按钮而不输入任何内容时,所有输入都有一个红色轮廓,但没有任何内容打印为field.errors。我不知道为什么会这样。 为什么会这样?

【问题讨论】:

【参考方案1】:
% load widget_tweaks %

<div class="col-12 col-md-6">
                        <div class="form-group">
                            <label for=" form.field1.id_for_label " class="text-capitalize"> form.field1.label|title % if form.field1.field.required %<span class="text-danger ml-1">*</span>% endif %</label>

                            % if form.is_bound %
                                % if form.field1.errors %
                                    % render_field form.name class="form-control is-invalid" %
                                    % for error in form.field1.errors %
                                        <div class="invalid-feedback">
                                         error 
                                        </div>
                                    % endfor %
                                % else %
                                    % render_field form.field1 class="form-control is-valid" %
                                % endif %
                            % else %
                                % render_field form.field1 class="form-control" %
                            % endif %

                            % if form.field1.help_text %
                                <small class="form-text text-muted"> form.field1.help_text </small>
                            % endif %
                        </div>
                    </div>
</div>

【讨论】:

在您的代码中,您正在循环访问我提到的所有字段,以保留每个字段手册。因此,在您的情况下,您必须将 field1 替换为您拥有的正确字段【参考方案2】:

你试过在模板中调试吗?

我做了你想要实现的事情:

<form method="post"> % csrf_token %
    % for field in form %
        <div class="form-group">
             field 
        <label class="control-label" for=" field.id_for_label "> field.label </label>
            % if field.errors %
                <div class="border-bottom-danger">
                     field.errors 
                </div>
            % endif %
        </div>
    % endfor %
    <button class="btn btn-block" type="submit">Submit</button>
</form>

地点:

    field 是输入,您在其中正确添加 visible.field.widget.attrs['class'] = 'form-control' 然后,您想要(我猜)的错误存储在该字段中,因此如果有的话,您可以使用 field.errors 获取它。

你的代码和我的不同之处在于我使用的是field.errors而不是if field.help_text,希望对你有帮助。

我建议您在模板中放置断点,然后分析您的form 对象。然后你可以在你的前端做任何你想做的事情。

    如果没有错误: 将类 outline-green 添加到您的输入包装器(&lt;div class="row"如果出现错误:在输入下方的 div 中显示错误

PS : 如果你想概述输入,而不是行包装,你可以通过 css 来完成(或者如果你正在使用它,最好使用 Sass):

.row.outline-green > input
   border: 1px solid green;
<div class="row outline-green">
 field 
</div>

【讨论】:

对此我有两个问题:1) 如何在模板中放置断点?我正在使用 Atom 和终端 - 我需要为此使用其他东西吗? 2) 我更新了我的问题 - field.errors 似乎是空的。你能解释一下为什么会这样吗? 1) Check on this thread。就个人而言,我正在使用 pycharm pro。 2)你真的得到 field.help_text 的错误吗?尝试放置一些断点,以查看job_listing_formemployer_form 是如何填充的。如果您不能在模板中,请在返回上下文之前尝试在视图中。使用断点进行调试将为您节省大量时间。 当前模板将None 打印为field.errors。我不是通过 PyCharm 设置断点(因为我只有社区版),而是通过您提供的链接中的第二个答案。断点仅在第一次渲染模板时被激活。如果我单击提交按钮,则不会再次触发断点。这对我来说很奇怪 - 我认为 Django 会在每个 POST 请求上重新呈现模板,即使它是无效的?也许这个错误与我的观点有关? 删除条件% if field.errors %之前的&lt;p&gt; field.errors &lt;/p&gt;。然后检查您的job_listing_form.visible_fields 是如何填充断点的。是否有任何变量带有您所期望的任何类型的错误。 PS:如果您需要在模板中进行深度调试(逐步),请试用 pycharm pro 及其试用版 30 天(还有学生版 1 年)。 field.errors 为空,因为消息“请填写此字段”。由网络浏览器呈现。即使我填写了其他输入字段并单击提交按钮,它实际上并没有向服务器发送 POST 请求,但浏览器只是呈现“请填写此字段”。再次。如何解决此浏览器功能,以便测试我的错误报告功能?

如何在 django 中使用 bootstrap4 设置酥脆的表格?

】如何在django中使用bootstrap4设置酥脆的表格?【英文标题】:Howtostylecrispyformswithbootstrap4indjango?【发布时间】:2022-01-0411:39:29【问题描述】:我正在尝试设置从脆表单使用的上传表单的样式。能否给我一个简单的解决方案,不要... 查看详情

如何在 twitter-bootstrap 模式窗口中插入 django 表单?

】如何在twitter-bootstrap模式窗口中插入django表单?【英文标题】:HowdoIinsertadjangoformintwitter-bootstrapmodalwindow?【发布时间】:2012-07-0119:55:18【问题描述】:四月份有人问过确切的samequestion,没有任何答案。但由于他提供的信息太少... 查看详情

我如何使用 Bootstrap4 模态在 Django 中制作功能正常的删除确认弹出窗口

】我如何使用Bootstrap4模态在Django中制作功能正常的删除确认弹出窗口【英文标题】:HowdoimakeafunctioningDeleteconfirmationpopupinDjangousingBootstrap4Modal【发布时间】:2020-08-1902:14:28【问题描述】:我的views.py文件如下所示。defdeleteOrder(reque... 查看详情

Django Bootstrap - 如何从本地 JSON 文件解析变量并将其显示在 .html 模板中?

】DjangoBootstrap-如何从本地JSON文件解析变量并将其显示在.html模板中?【英文标题】:DjangoBootstrap-HowtoparseavariablefromalocalJSONfileanddisplayitina.htmltemplate?【发布时间】:2021-03-2816:27:01【问题描述】:我是JS新手,想在我的html文件中显... 查看详情

如何使用 Bootstrap 在 Django 中自定义复选框和收音机?

】如何使用Bootstrap在Django中自定义复选框和收音机?【英文标题】:HowtocustomcheckboxandradioinDjangousingBootstrap?【发布时间】:2019-08-2409:02:17【问题描述】:我正在尝试使用引导类自定义Django中的复选框和收音机。但是,它并没有奏... 查看详情

如何在 Django 中向 bootstrap4 添加松脆的表单?

】如何在Django中向bootstrap4添加松脆的表单?【英文标题】:Howtoaddcrispyformstobootstrap4inDjango?【发布时间】:2022-01-0510:53:55【问题描述】:我在将引导上传表单与django表单(脆表单)结合起来时遇到了麻烦。知道如何将酥脆的表单... 查看详情

Django + ajax + 模态表单 bootstrap5.如何让它发挥作用?

】Django+ajax+模态表单bootstrap5.如何让它发挥作用?【英文标题】:Django+ajax+modalformbootstrap5.Howtomakeitwork?【发布时间】:2022-01-0219:10:21【问题描述】:无论我多么努力都没有尝试固定Ajax请求。在成功的情况下,应该发生重定向,在... 查看详情

如何自定义 django bootstrap 表单

】如何自定义djangobootstrap表单【英文标题】:HowtoCustomizedjangobootstrapform【发布时间】:2018-10-0213:51:30【问题描述】:我正在使用boostrap表单,但我需要在我的设计中对其进行自定义。当我简单地写<formclass="firstform"method="POST"encty... 查看详情

使用 Bootstrap 在 Django 中查看

】使用Bootstrap在Django中查看【英文标题】:SignupViewinDjangowithBootsrap【发布时间】:2016-09-0214:12:54【问题描述】:我是一名自学成才的程序员(初学者),正在尝试编写基于注册类的视图。通过一些教程,我已经能够编写如下代码... 查看详情

Django - 如何在使用 django-bootstrap-toolkit 登录(或)注册时验证用户身份?

】Django-如何在使用django-bootstrap-toolkit登录(或)注册时验证用户身份?【英文标题】:Django-HowtoAuthenticateuserswhileloggingin(or)registeringwhileusingdjango-bootstrap-toolkit?【发布时间】:2013-07-1214:48:35【问题描述】:我正在尝试在django中对... 查看详情

如何在 django REST 框架中修改 request.data

】如何在djangoREST框架中修改request.data【英文标题】:Howcanmodifyrequest.dataindjangoRESTframework【发布时间】:2016-02-2423:58:07【问题描述】:我正在使用DjangoREST框架request.data=\'"id":"10","user":"tom"\'我想添加额外的属性,比如"age":&qu... 查看详情

Django:如何在 post_save 信号中访问原始(未修改)实例

】Django:如何在post_save信号中访问原始(未修改)实例【英文标题】:Django:Howtoaccessoriginal(unmodified)instanceinpost_savesignal【发布时间】:2011-07-3117:51:39【问题描述】:我想进行数据非规范化以获得更好的性能,并将我的博客文章收... 查看详情

如何让数据表与 Django 模板中的 bootstrap4 选项卡一起使用?

】如何让数据表与Django模板中的bootstrap4选项卡一起使用?【英文标题】:HowdoIgetdatatablestoworkwithbootstrap4tabsinDjangotemplates?【发布时间】:2021-03-1219:28:34【问题描述】:我有一个包含多个表的Django模板。我正在使用带有数据表的Boot... 查看详情

如何在 Django 模板中显示分页?

...加分页。我按照Django的文档进行分页,但我在其中添加了Bootstrap的分页以提供美观的外观。但是,它确实显示在我的主页上。这里是index.html代码<divclas 查看详情

python测试开发django-120.bootstrap-table表格添加操作按钮(查看/修改/删除)(代码片段)

前言在table表格每一项后面添加3个操作按钮:查看/修改/删除,实现效果新增操作项接着前面这篇https://www.cnblogs.com/yoyoketang/p/15242055.html在columns最后添加一个操作项,formatter属性可以帮助我们更加灵活的显示表格中的内容#... 查看详情

在 Django Bootstrap Modal 窗口中编辑记录

】在DjangoBootstrapModal窗口中编辑记录【英文标题】:editingrecordsinDjangoBootstrapModalwindow【发布时间】:2016-11-0623:06:21【问题描述】:我正在尝试在Django中完成一个简单的应用程序,我需要在模式窗口中显示一组数据,对其进行更新... 查看详情

如何在 django 项目中使用引导样式

】如何在django项目中使用引导样式【英文标题】:Howtousebootstrapstylingindjangoproject【发布时间】:2018-07-2106:49:53【问题描述】:我已经下载了引导文件(css,js)并放入我的项目的static文件夹,并在index.html的标题部分进行了更改,... 查看详情

在 Django 中围绕 bootstrap html 标签封闭 For 循环

】在Django中围绕bootstraphtml标签封闭For循环【英文标题】:EnclosingForLoopinDjangoaroundbootstraphtmltags【发布时间】:2017-08-1102:51:46【问题描述】:我对Django上的Python很陌生。我喜欢将我的BootstrapHTML标签包裹在DjangoFor..Loop句柄周围,这... 查看详情