【问题标题】:Using JS to render Django form使用 JS 渲染 Django 表单
【发布时间】:2018-01-28 01:15:10
【问题描述】:

我正在学习在 Django 项目中使用纯 JS。作为服务器端开发人员,这些概念对我来说相对较新,所以需要帮助。

想象一个用户可以发布文本和/或上传图片的表单。把它想象成一个简单的 Django 表单,如下所示:

class PostForm(forms.Form):
    image = forms.ImageField(required=False)
    reply = forms.CharField(required=False, widget=forms.Textarea(attrs={'cols':30,'rows':3,'class': 'cxl','autocomplete': 'off','autofocus': 'autofocus'}))

    def __init__(self,*args,**kwargs):
        super(PostForm, self).__init__(*args,**kwargs)
        self.fields['image'].widget.attrs['id'] = 'browse_image_btn'

    def clean(self):
        data = self.cleaned_data
        # perform cleaning
        return data

如果我要在 HTML 中呈现此表单,则可以执行以下操作:

<form action="{% url 'post_content' %}" method="POST" enctype="multipart/form-data">
    {% csrf_token %}
    {{ post_form.reply }}<br>
    {{ post_form.image }}
    <label for="browse_image_btn" style="cursor: pointer;"><img alt="Select photo" src="{{ STATIC_URL }}img/upload.svg" width="70" height="70"></label>        
    <input type="submit" value="submit">
</form>

但是我如何仅通过 JS 创建这个 HTML 呢?

用例:想象一个包含一长串内容的页面,每个页面下方都有一个reply 按钮。上面的表格只有在用户按下reply 按钮后才会出现在特定内容下。此外,按下相同的按钮也可以切换off

我似乎无法全神贯注地解决这样的问题。请提供建议,最好提供说明性示例。我更愿意了解最有效、最可扩展的方法,一种可以部署在专业环境中的方法。只有纯 JS,没有 JQuery。


我已经对此进行了尝试,但是由于我是 JS 新手,因此它们是半生不熟的。到目前为止,这是我所得到的:

  var okBtn = document.createElement('button');
    setUpSubmitBtn(okBtn);
   e.target.parentNode.insertAdjacentElement('afterend', okBtn);

   var camBtn = document.createElement('img');
    setUpCameraBtn(camBtn);
   e.target.parentNode.insertAdjacentElement('afterend', lineBreak);
   e.target.parentNode.insertAdjacentElement('afterend', camBtn);

   var replyBox = document.createElement('textarea');
    setUpReplyBox(replyBox);
   e.target.parentNode.insertAdjacentElement('afterend', replyBox);

上面提到的每个小部件都有简单的 JS 函数来创建:

function setUpReplyBox(replyBox) {
    replyBox.classList.add('mts');
    replyBox.setAttribute('id', 'reply-message');
    replyBox.setAttribute('style', 'display:inline');
    replyBox.setAttribute('placeholder', 'Reply');
}

function setUpSubmitBtn(okBtn) {
    okBtn.classList.add('btn', 'bcb', 'bs', 'mts');
    okBtn.setAttribute('style','border:none;height:25px;display:inline;');
    okBtn.setAttribute('id','reply-ok');
    okBtn.innerHTML = "OK";
}

function setUpCameraBtn(camBtn) {
    camBtn.setAttribute('id','camera');
    camBtn.setAttribute('src','/static/img/cam1.svg');
    camBtn.setAttribute('width','45');
    camBtn.setAttribute('height','45');
    camBtn.setAttribute('style','display:inline;float:right;');
}

我觉得我做这件事的方式很难/错误。正确的模式可能会简单得多。

【问题讨论】:

  • 只渲染所有表单,不显示,然后用js切换或渲染一个并用js移动(动态更改id)
  • @bigless:我只是想知道使用 display:none 渲染所有表单是否可行。我更喜欢你的第二个建议;关于渲染一个并用 JS 移动它。但这将如何运作?我会做position: absolute; top: -9999px; left: -9999px;,然后用 JS 将其移动到位吗?很高兴从您那里获得有关此主题的快速入门示例。

标签: javascript django


【解决方案1】:

希望对你有帮助:

var formTemplate = document.querySelector('#form-template form');
var idInput = document.getElementById('id-input');

function toggleReply(e) {
  if (!formTemplate) return;

  e.target.parentNode.insertBefore(formTemplate, e.target);
  idInput.value = e.target.getAttribute('data-id');
};

Array.from(document.querySelectorAll('button.reply'))
  .forEach(btn => btn.onclick = toggleReply)
form + .reply {
  display: none;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>

<div id="form-template" style="display: none;">
  <form action="" method="POST" enctype="multipart/form-data">
      <input id="id-input" type="hidden" name="id" value="">
      <div class="form-group">
        <label for="reply">Reply:</label>
        <textarea class="form-control" type="text" name="text"></textarea>
      </div>
      <input type="submit" class="btn btn-default pull-right" value="submit">
  </form>
</div>

<div class="container">
  <div class="list-group">
    <div class="panel panel-default">
      <div class="panel-heading">
        <h3 class="panel-title">Comment title</h3>
      </div>
      <div class="panel-body">
        Comment content
      </div>
      <div class="panel-footer clearfix">
        <button class="reply btn btn-default pull-right" type="button" data-id="24">Reply</button>
      </div>
    </div>
    <div class="panel panel-default">
      <div class="panel-heading">
        <h3 class="panel-title">Comment title</h3>
      </div>
      <div class="panel-body">
        Comment content
      </div>
      <div class="panel-footer clearfix">
        <button class="reply btn btn-default pull-right" type="button" data-id="25">Reply</button>
      </div>
    </div>
  </div>
</div>

【讨论】:

  • 谢谢你,我正在处理这个。不过有一件事:我正在做的练习是纯 JS,而不是 JQuery。你能把JQuery代码改成JS吗?
  • @HassanBaig 已更新,但请记住使用原版操作 DOM 可能会很痛苦。
  • 谢谢。作为学习目标,我想我会学习纯 JS 概念,然后转向更强大的 JQuery。但是,我周围有很多关于 React.JS 的讨论。对于想要提高客户端能力的人来说,对于习惯使用哪个库,您有什么建议?
  • @HassanBaig 请注意,我不喜欢 jQuery,但如果您想要动态前端而不重写后端,这是最快的方法。我不知道 ReactJS 但猜测它的前端 mvc 与 angular 相同。它适用于需要许多用户交互的网站,如管理员等。Con 需要编写 restapi。
  • 一旦按下回复按钮,保存在div 中的ID 为form-template 的表单就会插入到不同的位置。如果按下第二个回复按钮,该表单将再次移动。但是,到那时,该表单不再位于 ID 为 form-templatediv 中(它已经移动了一次)。那么var formTemplate = document.querySelector('#form-template form'); 到底是如何每次都正确填充的呢?我认为#form-template form 的意思是选择id 为form-template 的元素内的表单。希望得到一些关于添加到您的答案中的解释
猜你喜欢
  • 1970-01-01
  • 2018-11-13
  • 2013-10-10
  • 2018-12-22
  • 2015-12-30
  • 2019-07-08
  • 2017-12-03
  • 2016-08-23
  • 2020-10-19
相关资源
最近更新 更多