【问题标题】:Multiple Choice Field Saving多项选择字段保存
【发布时间】:2013-07-23 17:22:02
【问题描述】:

我正在使用这样的模型开发一个 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)]

我能够使用上面的代码正确呈现选择多个元素。我将 kwargs 从视图传递到 get_form_kwargs 上的表单。

现在的问题是一种有效地从 RSVP 表中添加/删除客人的方法。我犹豫要不要继续,因为我无法在下面提出的解决方案之间做出决定:

  1. 每次在 UI 中发生事件时处理表单 - 当用户选择来宾时,它会立即添加到表格中;当用户取消选择用户时,来宾将从 RSVP 表中删除。如果客人数量增加,这可能会导致大量 SQL 读取/写入。

  2. 在提交表单之前不会保存任何内容 - 从发布的数据中,我将创建一个选定选项的字典,将其与加载表单时的状态进行比较,任何新行都是添加和缺失的行将从表中删除。这只需要 2 个 SQL 操作。

任何人都可以帮助提出一个好的解决方法或更好的想法来解决这个问题吗?我的建议中是否存在我可能忽略的问题?

【问题讨论】:

    标签: jquery django django-views


    【解决方案1】:

    我决定暂时采用解决方案 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)
    

    有什么改进建议吗?

    【讨论】:

      猜你喜欢
      • 2021-11-16
      • 1970-01-01
      • 2020-09-30
      • 1970-01-01
      • 2011-02-13
      • 2017-02-18
      • 1970-01-01
      • 2017-12-24
      • 1970-01-01
      相关资源
      最近更新 更多