2

参加者をアタッチできる一種のスケジューライベントエディタを作成しようとしています。

モデル

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)

userエディターで、セッションに追加するsを見つけることができるオートコンプリート検索入力が必要です

プレビュー

セッションエディタ

ここでは「laurent」と入力し、結果の名前の1つをクリックして人を追加します
。参加者の色は彼らに依存しますstatus

Session開始時刻と終了時刻で定義されたオブジェクトのフォームがあります。これで、sのインライン
フォームセット が必要になると思います。Participation

質問

  • 参加者にインラインフォームセットを使用することをお勧めしますか?
  • 参加者の行を動的に追加/削除するにはどうすればよいですか?
4

2 に答える 2

6

質問は非常に単純に見えますが、適切な回答にはいくつかの回答が含まれます。

jQueryを使用して、ソリューションを1つずつ示します。

オートコンプリート

これは単純な部分です。select2やjqueryuiオートコンプリートなどのプラグインと、次のようなユーザーを検索するビューを使用できます。

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)

このビューは、デフォルトのjQueryUIオートコンプリートプラグインと互換性があります

動的フォームセット

これはトリッキーなものです。重要なのは、とを利用することmanagement_formですform.DELETE。これが私の解決策です:

  • 参加者用のインラインフォームセットを使用します(追加のフォームが1つあります)
  • 印刷する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インスタンスを使用してIDを置き換えることもできることは知っています__prefix__が、これによりJavaScriptが簡素化され、保守性が向上しますが、コードを実際の形式と空の形式の間で因数分解する方法が見つかりませんでした。

意見

inlineformset_factoryビューは、1に設定して使用するのはかなり標準的ですextra(複製する唯一の非表示のフォームを取得するため)。HiddenInputまた、フィールドにウィジェットを使用することを忘れないでくださいparticipant

于 2012-04-26T16:14:55.073 に答える
1

このプラグインは、探しているオートコンプリート機能を取得するのに役立ちます。

https://github.com/millioner/django-ajax-select

于 2012-04-26T17:57:50.000 に答える