web-dev-qa-db-ja.com

Djangoフォームの数が不明なチェックボックスフィールドと複数のアクション

Gmailの受信トレイのように見え、複数のアクションがあるフォームについてサポートが必要です。アイテムのリストがあり、すべてのアイテムの行の前にチェックボックスがあるように、フォームでラップしたいと思います。したがって、ユーザーがいくつかのアイテムを選択すると、削除や既読のマークなど、アクションが異なる2つのボタンをクリックできます。

<form action="">
    {% for item in object_list %}
    <input type="checkbox" id="item.id">
    {{ item.name }}
    {% endfor %}
    <button type="submit" name="delete">Delete</button>
    <button type="submit" name="mark_read">Mark read</button>
</form>

if 'delete' in request.POSTを使用すると、ユーザーがクリックした送信ボタンを見つけることができますが、Djangoフォームは、不明な数のフィールドで定義できないため、フォームを参照できません。選択したアイテムをビューで処理できますか?

if request.method == 'POST':
    form = UnknownForm(request.POST):
    if 'delete' in request.POST:
        'delete selected items'
    if 'mark_read' in erquest.POST:
        'mark selected items as read'
    return HttpResponseRedirect('')
14
Goran

同じ名前の複数のチェックボックスはすべて同じフィールドです。

<input type="checkbox" value="{{item.id}}" name="choices">
<input type="checkbox" value="{{item.id}}" name="choices">
<input type="checkbox" value="{{item.id}}" name="choices">

単一のDjangoフォームフィールドでそれらを収集して集約できます。

class UnknownForm(forms.Form):
    choices = forms.MultipleChoiceField(
        choices = LIST_OF_VALID_CHOICES, # this is optional
        widget  = forms.CheckboxSelectMultiple,
    )

具体的には、ModelMultipleChoiceFieldを使用できます。

class UnknownForm(forms.Form):
    choices = forms.ModelMultipleChoiceField(
        queryset = queryset_of_valid_choices, # not optional, use .all() if unsure
        widget  = forms.CheckboxSelectMultiple,
    )

if request.method == 'POST':
    form = UnknownForm(request.POST):
    if 'delete' in request.POST:
        for item in form.cleaned_data['choices']:
            item.delete()
    if 'mark_read' in request.POST:
        for item in form.cleaned_data['choices']:
            item.read = True; item.save()
28
Thomas

トーマスの解決策についてはコメントできないので、ここで説明します。

ModelMultipleChoiceFieldの場合、引数名は選択肢ではなくクエリセットです。

したがって、最後の例をとると:

class UnknownForm(forms.Form):
choices = forms.ModelMultipleChoiceField(
    choices = queryset_of_valid_choices, # not optional, use .all() if unsure
    widget  = forms.CheckboxSelectMultiple,
)
5
y0no

クラスベースビューを使用して、Django HTMLテンプレート内の不明なサイズのリストを反復処理することで、これと同じ問題が発生していました。

このソリューションは「post」を使用し、私のために機能します。上記の解決策は役に立ちましたが、ループの問題は解決しなかったので、これをここに置きます。

HTMLテンプレート:

<form action="" method="post">
    {% for item in object_list %}
        <input type="checkbox" value="{{item.id}}" name="my_object">
        {{ item.name }}
    {% endfor %}
    <button type="submit" name="delete">Delete</button>
    <button type="submit" name="mark_read">Mark read</button>
</form>

形:

class MyForm(forms.Form):
    my_object = forms.MultipleChoiceField(
        widget=forms.CheckboxSelectMultiple,
    )

クラスベースのビューで、post関数を使用してPOSTデータにアクセスします。これにより、チェック済みアイテムのリスト、コンテキスト、およびその他のフォームデータにアクセスできます。

見る:

Class MyView(FormView):
    template_name = "myawesometemplate.html"
    form_class = MyForm
...
# add your code here 

    def post(self, request, *args, **kwargs):
        ...
        context = self.get_context_data()
        ...
        if 'delete' in request.POST:
            for item in form.POST.getlist('my_object'):
                # Delete
        if 'mark_read' in request.POST:
            for item in form.POST.getlist('my_object'):
                # Mark as read
5
imapotatoe123

これは、ユーザーにグループまたはアクセス許可を追加するときに非常に役立つことがわかりました。

ページのビューにデフォルトのDjangoグループと権限が含まれていることを確認してください。

from Django.contrib.auth.models import Permission, Group

データベーステーブルから選択肢を取得する場合は、ウィジェットでDjangoフォームオブジェクトを使用して、使用可能なすべての選択肢を動的に読み込むことができます。また、フォーム名がであるかどうかを確認する必要があります。モデル名と同じです。

    groups = forms.ModelMultipleChoiceField(label='Groups', required=False, queryset=Group.objects.all(), widget=forms.CheckboxSelectMultiple)
user_permissions = forms.ModelMultipleChoiceField(label='Permissions', required=False, queryset=Permission.objects.all(), widget=forms.CheckboxSelectMultiple)

次に、そのページのviewメソッドのpostセクションで、選択した選択肢を選択肢オブジェクトのリストとして返し、forループを使用してそれらをユーザーオブジェクトに追加できます。

u.save()  # required to save twice, so this saves the other form fields.
        user.groups.clear()
        u.user_permissions.clear()
        # print('Group name:', form.cleaned_data['groups'])
        for group in form.cleaned_data['groups']:
            print(group)  # Prints to your console for debugging
            user.groups.add(group)
        for permission in form.cleaned_data['user_permissions']:
            print(permission)  # Prints to your console for debugging
            user.user_permissions.add(permission)
        u.save()  #This saves the groups and permissions

グループが選択されていない場合でも、これにはいくつかのロジックが必要になる場合がありますが、開始するには十分なはずです。

0
Jason Smith