Django的 - 的JavaScript动态在线表单集与自动完成 [英] Django - Javascript dynamic inline FormSet with autocomplete

查看:121
本文介绍了Django的 - 的JavaScript动态在线表单集与自动完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图做出一种调度事件编辑器与附加参与者的能力。

I'm trying to make a kind of scheduler event editor with the ability to attach participants.

class Session(models.Model):
  start_time = models.DateTimeField()
  end_time = models.DateTimeField()

class Participation(models.Model):
  session = models.ForeignKey(Session)
  participant = models.ForeignKey(User)
  status = models.CharField(max_length=1, choices=STATUSES)

在编辑器中,我想有一个自动完成搜索输入从中我可以找到用户 s到添加到会话

In the editor I'd like to have an autocomplete search input from which I can find users to add to the session

在这里,我已经输入劳伦特我要去点击地名由此而来的一个增加一个人的结果
参与者颜色取决于他们的状态

Here I have typed "laurent" and I'm going to add a person by clicking on one of the resulting names
Participant colors depend on their status

我有带启动和放大器定义的会话对象的形式;结束时间结果
现在,我想我应该有一个的在线表单集的为参与取值

I have a form for the Session object defined with start & end times
Now I think I should have an inline formset for Participations


  • 请您建议我使用的在线表单集的为学员?

  • 如何动态添加/删除参与者行?

推荐答案

这个问题似乎很简单,但适当的回应将涉及几个答案。

The question seems very simple but a proper response would involve several answers.

我会点给我的解决方案来看,使用jQuery。

I will give my solutions point by point, using jQuery.

这是一个简单的一部分。您可以使用像 SELECT2 或的 jQueryUI的自动完成和发现用户喜欢

This is the simple part. You can use a plugin like select2 or jqueryui autocomplete and a view that finds users like

def search_users(request):
    search = request.GET.get('term')
    users = User.objects.filter(
      Q(first_name__icontains=search)
    | Q(last_name__icontains=search)
    )
    ulist = list({'id': u.id, 'value': u'%s %s' % (u.first_name, u.last_name)}
        for u in users)
    return JsonResponse(ulist)

此观点与默认的jQuery UI的自动完成插件

这是很棘手的。关键是要采取 management_form form.DELETE 的优势。这里是我的解决方案:

This is the tricky one. The key is to take advantage of management_form and form.DELETE. Here is my solution:


  • 使用内联表单集的参与者(有一个额外的表格)

  • 打印 management_form

  • 使用jQuery添加表格线自动完成选择后,通过克隆一个隐藏的空单(额外的一个)和递增 id_form-TOTAL_FORMS

  • 通过隐藏它们,检查隐藏删除复选框删除与jQuery表格线

<form method="post">{% csrf_token %}
{{ sessionform }}
<div>
{{ participant_formset.management_form }}
  <label for="part_search">Search: </label><input id="part_search" />
    <ul id="participation_set">
{% for tform in participant_formset %}
    {{ tform.id }}
      <li>
        <span class="participant">
          {{ tform.participant }}{{ tform.instance.participant.name }}
        </span>
        <span class="status">{{ tform.status }}</span>
        <span class="delete ui-icon ui-icon-circle-minus">
          {{ tform.DELETE }}
        </span>
      </li>
{% endfor %}
    </ul>
</div>
</form>

的CSS

/* Delete button */
#participation_set .delete {
  display: inline-block;
  vertical-align: middle;
  cursor: pointer;
}

/* Hidden delete checkbox */
#participation_set .delete input {
  display: none;
}

/* Deleted form */
#participation_set li.deleted {
  display: none;
}

/* Last hidden form to clone */
#participation_set li:last-child {
  display: none;
}

的jQuery

/*! This adds a form line
 * Call it on autocomplete select
 */
function add_aform(inst, item) {
  if ($(':input[name$="participant"][value=' + item.id + ']').length) {
    return false;
  }
  var total = $('#id_' + inst + '-TOTAL_FORMS').val();
  var sul = '#' + inst;
  var li = $(sul + ' li:last-child');
  var new_li = li.clone().appendTo(sul);
  li.find('span.participant').append(item.label);
  li.find(':input[name$="participant"]').val(item.id);
  new_li.find(':input').each(function () {
    var new_name = $(this).attr('name')
      .replace('-' + (total - 1) + '-', '-' + total + '-');
    $(this).attr('name', new_name);
  });
  new_li.find('label').each(function () {
    var tmp = $(this).attr('for')
      .replace('-' + (total - 1) + '-', '-' + total + '-');
    $(this).attr('for', new_for);
  });
  new_li.find('.delete').click(del_aform);
  $('#id_' + inst + '-TOTAL_FORMS').val(++total);
}

/*! This removes a form line
 * Call it on click from delete buttons (placed inside each li)
 */
function del_aform() {
  $(this).parents('li').addClass('deleted');
  $(this).find(':checkbox').attr('checked', true);
}

我知道我还可以使用 empty_form 实例,并使用 __ preFIX __ 来代替IDS其中简化了更好的可维护性的JavaScript,但我没有找到一个方法来因式分解真实的形式和空单间code。

I know I could also use an empty_form instance and use __prefix__ to replace the ids which simplifies the javascript for a better maintainability, but I didn't find a way to factorize the code between the true form and the empty one.

该视图是使用pretty标准 inlineformset_factory 额外的设置为1(以得到的唯一隐患形成克隆)。另外,不要忘记用 HiddenInput 窗口小部件领域参与者

The view is pretty standard using inlineformset_factory with extra set to 1 (to get the only hidden form to clone). Also don't forget to use a HiddenInput widget for the field participant

这篇关于Django的 - 的JavaScript动态在线表单集与自动完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆