from collections import defaultdict from django import forms import models import transports import widgets class SubscriptionForm(forms.Form): def __init__(self, *args, **kwargs): self.user = kwargs.pop('user') self.site = kwargs.pop('site') self.categories = models.Category.objects.filter(site=self.site) self.subscriptions = models.Subscription.objects.filter(user=self.user) sub_by_category = defaultdict(lambda: []) for sub in self.subscriptions: sub_by_category[sub.category].append(sub.transport) super(SubscriptionForm, self).__init__(*args, **kwargs) self.choices = list(transports.get_transport_choices()) for category in self.categories: field = forms.MultipleChoiceField( label=category.name, choices=self.choices, widget=widgets.CheckboxMultipleSelect, initial=sub_by_category[category], required=False) self.fields['category_%s' % category.identifier] = field def save(self): cleaned_data = self.cleaned_data wanted_subscriptions = set() for category in self.categories: field_id = 'category_%s' % category.identifier transports = cleaned_data.get(field_id, []) for transport in transports: wanted_subscriptions.add((category, transport)) # delete dead subscriptions for subscription in self.subscriptions: pair = (subscription.category, subscription.transport) if pair not in wanted_subscriptions: subscription.delete() # create or update new ones for category, transport in wanted_subscriptions: models.Subscription.objects.get_or_create( user=self.user, category=category, transport=transport)