【问题标题】:Don't include blank fields in GET request emitted by Django form不要在 Django 表单发出的 GET 请求中包含空白字段
【发布时间】:2013-08-23 18:57:03
【问题描述】:

在我的 Django 网站上,我有一个包含几个可选字段的搜索页面。搜索页面是django表单,我的视图功能比较典型:

def search(request):
    form = SearchForm(request.GET or None)
    if form.is_valid():
        return form.display_results(request)

    return render(request, 'search.html', {'form': form})

Form.display_results() 使用提供的字段来查询数据库并呈现响应。我的 search.html 包括:

<form action="/search/" method="get">{% csrf_token %}
    <!-- Render the form fields -->
    <input type="submit" value="Search" />
    <input type="reset" value="Reset form" />
</form>

由于大多数搜索都会有几个空白字段,我不想将它们包含在 search.html 上的提交按钮发出的 GET 请求中。当前搜索类似于:

http://mysite/search/?csrfmiddlewaretoken=blah&optional_field1=&optional_field2=&optional_field3=oohIWantThisOne

我希望它们看起来像:

http://mysite/search/?csrfmiddlewaretoken=blah&optional_field3=oohIWantThisOne

当然,我还有几个字段。这将是很好的,因为它会使搜索 URL 更容易被人类解析和共享。

【问题讨论】:

    标签: django django-forms


    【解决方案1】:

    您可以将 jQuery 与按钮触发器一起使用。提供表单并提交按钮 ID。

    $("#button_id").click(function(){
        $("input").each(function(){
            if($(this).val() == '') {
                $(this).remove();
            }
        });
        $("#form_id").submit();
    });
    

    那(或类似的东西)应该在提交之前删除所有空字段。

    【讨论】:

    • 这种方法的问题是,如果表单由于某种原因(例如验证)没有提交,这些输入将消失。也许您可以将函数直接附加到submit 方法。
    • 正确 - 浏览器提交表单上的所有成功控件 (w3.org/TR/html401/interact/forms.html#h-17.13.2),因此唯一可行的方法是使用某种 JavaScript 删除或停用不必要的控件。另请注意,如果您打算传递这些 URL,您真的不希望您的 CSRF 令牌包含在其中。 GET 请求会忽略 CSRF 令牌,但这仍然是不必要的,也是一种不好的做法。
    • 我真的认为发布表单的另一种解决方案更简洁。
    • 嗯。然后将相关参数插入到响应的 URL 中,并确保该 URL 以后可以实现?是的,这也没什么不好。我想我的意思是“处理 GET 请求的唯一方法是使用 Javascript……”。
    • 此功能对我的网站没有影响。我检查了js控制台,没有错误。我还通过手动调用该函数进行了测试,它确实按预期提交了表单。尽管如此,该 URL 仍包含空的 GET 参数。有任何想法吗?使用 jquery 版本 1.12.4(通过 Google CDN)。
    【解决方案2】:

    您也可以发布表单。然后构建搜索 url 并在删除空值的情况下重定向。

    【讨论】:

    • 使用POST 的恼人之处在于不能共享带有预填充搜索参数的链接,甚至在站点上的视图之间也不能共享(至少没有javascript 技巧)。这很烦人。
    • 所以使用 POST 数据来构建 url 参数,忽略空的。然后这个网址就可以收藏了。
    【解决方案3】:

    参见比尔·埃里克森的Hide empty fields from GET form

    jQuery(document).ready(function($){
    
      // Remove empty fields from GET forms
      // Author: Bill Erickson
      // URL: http://www.billerickson.net/code/hide-empty-fields-get-form/
    
      // Change 'form' to class or ID of your specific form
      $("form").submit(function() {
        $(this).find(":input").filter(function(){ return !this.value; }).attr("disabled", "disabled");
        return true; // ensure form still submits
      });
    
      // Un-disable form fields when page loads, in case they click back after submission
      $("form").find(":input").prop("disabled", false);
    }
    

    【讨论】:

      【解决方案4】:

      免责声明:这是一个非常古老的问题,也是我能找到的唯一一个与我遇到的问题相匹配的问题。完全有可能我的解决方案当时不存在,后来添加了更好的方法。

      我正在使用 Django 3.2。我不想使用 js/jQuery,也不想使用 POST 表单,所以这就是我想出的。简而言之,它只是检查 GET 数据以查看是否存在任何默认值,然后简单地重定向到没有它们的 URL。

      在你看来:

      from django.shortcuts import redirect
      
      def myView(request):
          if not is_clean_form(request.GET):
              return redirect(whatever_url_path + clean_url_parameters(request.GET))
          else:
              # whatever your view does normally
      

      Helper 函数(考虑为您的 Form 类创建这些静态方法,以将所有这些类型的东西放在一起):

      from urllib.parse import urlencode
      
      # fields and their default value (eg. empty string)
      default_form_values = [
          ("some_field_name", ""),
          # ...
      ]
      
      def is_clean_form(form_dict):
          for field, default_value in default_form_values:
              if field in form_dict and form_dict[field] == default_value:
                  return False
          return True
      
      def clean_url_parameters(form_dict):
          return "/?" + urlencode([
              (field, form_dict[field]) for (field, default_value) in default_form_values
              if field in form_dict and form_dict[field] != default_value
          ])
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-05-05
        • 1970-01-01
        • 1970-01-01
        • 2013-12-17
        • 1970-01-01
        • 2018-06-12
        • 2021-02-08
        • 2020-08-24
        相关资源
        最近更新 更多