0

私は次のようなモデルを使用して RSVP アプリに取り組んでいます。

class Guest(models.Model):
    profile = models.ForeignKey(UserProfile)
    ...
    invite_list = models.ManyToManyField(GuestList, through='RSVP')


class RSVP(models.Model):
    guestlist = models.ForeignKey(GuestList)
    guest = models.ForeignKey(Guest, related_name='rsvp')
    ...

また、ユーザーが追加するゲストを選択できる複数選択フィールド フォームを作成しようとしていますRSVP。jQuery を使用して複数選択を 2 つのボックスに拡張しています。選択した項目は右側のボックスに表示されます。

forms.py で、次を使用しcrispy_formsます。

class RSVPSelectGuestForm(forms.Form):    
    guests = forms.MultipleChoiceField()

    def __init__(self, *args, **kwargs):
        profile = kwargs.pop('profile', None)
        guestlist_pk = kwargs.pop('guestlist_pk', None)
        super(RSVPSelectGuestForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.layout = Layout(
            Field('guests', 
                id='guests-multiple-select',
            ),
            FormActions(
                Submit('submit', 'Save'),
            ),       
        )
        self.fields['guests'].choices = [(obj.id, str(obj)) for obj in Guest.objects.filter(profile=profile)]
        self.fields['guests'].initial = [(obj.guest_id) for obj in RSVP.objects.filter(guestlist_id=guestlist_pk)]

上記のコードを使用して、select multiple 要素を適切にレンダリングできます。上のフォームにビューから kwargs を渡しますget_form_kwargs

質問は、効率的な方法で RSVP テーブルからゲストを追加/削除する方法です。以下の提案された解決策の間で決定できないため、先に進むのをためらっています。

  1. UI でイベントが発生するたびにフォームを処理します。ユーザーがゲストを選択すると、すぐにテーブルに追加されます。ユーザーがユーザーの選択を解除すると、ゲストは RSVP テーブルから削除されます。これにより、ゲストの数が増えると、多くの SQL 読み取り/書き込みが発生する可能性があります。

  2. フォームが送信されるまで何も保存されません- 投稿データから、選択したオプションの辞書を作成し、フォームが読み込まれたときの状態と比較し、新しい行が追加され、欠落している行がテーブルから削除されます。これには、2 つの SQL 操作のみが必要です。

この問題を解決するための良い回避策やより良いアイデアを提案してくれる人はいますか? 私の提案で見落としている可能性のある問題はありますか?

4

1 に答える 1

0

解決策 2 の方が達成しやすかったので、今のところ解決策 2 を使用することにしました。フォームに以下のメソッドを追加し、フォーム保存時に2組のデータを作成して比較します。[Python の方が簡単] 次に、一括作成または一括削除にそれぞれ 1 つのクエリを使用するだけです。このコードを大規模なデータ セットでまだテストしていません。

def add_guests(self, added):
    RSVP.objects.bulk_create([
        RSVP(guestlist_id=self.guestlist_pk, guest_id=guest_pk) 
        for guest_pk in added
    ])

def remove_guests(self, removed):
    RSVP.objects.filter(guestlist_id=self.guestlist_pk, 
        guest_id__in=removed).delete()

def save(self):
    data = self.cleaned_data

    initial_data = set(self.initial_data)
    new_data = set([int(i) for i in data['guests']])

    added = new_data - initial_data
    removed = initial_data - new_data

    if added:
        self.add_guests(added)
    if removed:
        self.remove_guests(removed)

改善のための提案はありますか?

于 2013-07-24T05:19:25.183 に答える