我有一个相当复杂的用例,我需要比较两个字典列表,但是列表可以处于各种不同的状态,理想情况下,我希望能够在一个列表中处理所有这些字典。在
这样做的背景是,我有一个表单,它被呈现为一个复选框表,并且我试图获得表单的初始数据与更新时返回的cleaned_data
之间的差异(即选中或取消选中复选框)。在
所以通常初始数据只包含选中复选框的数据,例如
initial_data = [<Event: Event object>, <Event: Event object>, <Event: Event object>, <Event: Event object>]
当一个事件对象包含一个id和一个名称时,它们可以是同一个事件。在
如果未选中复选框,则cleaned_data
可能如下所示:
在本例中,我希望从初始的_数据中获取事件,其中清理后的_数据中没有事件。下一个用例是,如果选中复选框,则初始数据可能如下所示:
initial_data = [<Event: Event object>, <Event: Event object>]
然后像这样清理数据:
cleaned_data = [<Event: Event object>, <Event: Event object>, <Event: Event object>, <Event: Event object>]
在本例中,我希望从已清理的\u数据中返回与初始的\u数据不匹配的事件。在
还有第三部分使事情复杂化,如果有一行没有选中的复选框,它也会显示为无。所以我还需要处理这个问题:
initial_data = [<Event: Event object>, <Event: Event object>]
cleaned_data = [<Event: Event object>, None, <Event: Event object>, <Event: Event object>]
因此,为了澄清我要做的是,如果在cleaned_data
中有对应的None,则返回初始事件数据;如果与初始数据的cleaned_data
存在差异,则返回事件和None,并删除None。在
我想做点什么:
events = [[x for x in cleaned_data if x not in initial_data], [x for x in initial_data if x not in cleaned_data]]
但这只适用于我的一个用例(它适用于第二个用例,但对于第一个用例,它返回none而不是事件)。在
如果你能帮上忙,我会非常感激的,因为我觉得我已经很接近了,但我就是想不起来了!在
谢谢你的时间。在
另外,这是Django
应用程序的一部分
--编辑--
表单代码如下:
class ActivityGroupInline(InlineFormSet):
model = models.ActivityGroup
fields = ['events',]
can_delete = False
extra = 0
@property
def widgets(self):
return {
'events': widgets.CheckboxSelectMultiple(),
}
def get_factory_kwargs(self):
kwargs = super().get_factory_kwargs()
kwargs.update({
'widgets': self.widgets,
})
return kwargs
class ActivityGroupEventLink(NamedFormsetsMixin, UpdateWithInlinesView):
model = models.Container
fields = []
template_name = 'main/link_activitygroupsevents.html'
success_url = reverse_lazy('dashboard')
inlines = [ActivityGroupInline,]
inlines_names = ['activitygroup_inline',]
def get_object(self, queryset=None):
return models.Container.objects.first()
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context['breadcrumbs'] = [
{'name': 'Home', 'url': reverse_lazy('dashboard')},
{'name': 'Link Activities to Events', 'is_active': True}
]
all_events = models.Event.objects.filter(
container=context['object'],
).all()
context['events'] = { event.id: event for event in all_events }
for form in context['activitygroup_inline'].forms:
activitygroup_kcs = set(form.instance.key_characteristics.all())
potential_event_ids = set()
for event in all_events:
event_kcs = set(event.key_characteristics.all())
if event_kcs & activitygroup_kcs:
potential_event_ids.add(event.id)
form.fields['events'].choices = models.Event.objects.filter(
id__in=list(potential_event_ids)
).order_by('id').values_list('id', 'name')
return context
def forms_valid(self, form, inlines):
self.object = form.save()
for formset in inlines:
instances = formset.save(commit=False)
for inst in instances:
initial_events = [] # This is code I added to work with the solution that I am now trying
new_events = []
for f in formset:
initial_events.append(f.initial['events']) # This is code I added to work with the solution that I am now trying
new_events.append(f.cleaned_data['events'].first())
flat_initial = [item for sublist in initial_events for item in sublist] # This is code I added to work with the solution that I am now trying
try:
event = next(event for event in new_events if event is not None) # This is what I was previously doing to find the relevant event but it only works if there is one column in the table.
except StopIteration:
raise ValidationError('There must be at least one Activity Group linked to an event.')
activityevent = inst.activityevent_set.filter(activity_group_id=inst.id, event_id=event.id)
if activityevent.exists():
activityevent.delete()
else:
new_activityevent = models.ActivityEvent.objects.create(
activity_group=inst,
event=event,
)
new_activityevent.save()
inst.save()
return HttpResponseRedirect(self.get_success_url())
它还使用django外部形式。基本上,activity_group和event都有一个中间模型activityevent,因此当创建一个新链接时,还需要创建一个新的activityevent,并且需要在删除链接时删除它。在
--编辑2--
表单本身如下所示:
我只关心这个问题的复选框
目前没有回答
相关问题 更多 >
编程相关推荐