python - 比较两个 Django 模型实例列表
问题描述
我有一个相当复杂的用例,我需要比较两个字典列表,但是列表可以处于多种不同的状态,理想情况下我希望能够在一个中处理所有这些状态。
这的背景是我有一个呈现为复选框表的表单,我试图获取表单的初始数据与cleaned_data
进行更新时发送回的数据之间的差异(即选中复选框或未选中)。
因此,通常初始数据将仅包含选中复选框的数据,例如
initial_data = [<Event: Event object>, <Event: Event object>, <Event: Event object>, <Event: Event object>]
如果一个 Event 对象包含一个 id 和一个名称,它们可以是相同的,因为它可能是同一个事件。
如果未选中复选框,则cleaned_data
可能如下所示:
cleaned_data = [<Event: Event object>, None, <Event: Event object>, None]
在这种情况下,我想从initial_data 中获取事件,其中cleaned_data 中没有。下一个用例是,如果选中复选框,则初始数据可能如下所示:
initial_data = [<Event: Event object>, <Event: Event object>]
然后像这样清理数据:
cleaned_data = [<Event: Event object>, <Event: Event object>, <Event: Event object>, <Event: Event object>]
在这种情况下,我想从cleaned_data 中返回与initial_data 不匹配的事件。
还有第三部分使事情复杂化,如果有一行没有选中的复选框,它也显示为无。所以我还需要处理:
initial_data = [<Event: Event object>, <Event: Event object>]
cleaned_data = [<Event: Event object>, None, <Event: Event object>, <Event: Event object>]
因此,为了澄清我想要做的是返回初始事件数据,如果表单中有相应的无,cleaned_data
如果与初始数据有差异,则返回事件和无,cleaned_data
并删除无。
我一直在尝试这样做:
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]]
但这仅适用于我的一个用例(它适用于第二种情况,但第一种情况它返回 Nones 而不是事件)。
对此的任何帮助将不胜感激,因为我觉得我已经很接近了,但我无法在脑海中弄清楚!
谢谢你的时间。
PS这是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-extraforms。基本上,activity_group 和 event 有一个中间模型 activityevent,所以当建立一个新链接时,也需要建立一个新的 activityevent,并且在删除链接时需要删除它。
--EDIT2--
表单本身如下所示:
我只关心这个问题的复选框
解决方案
推荐阅读
- spring - 将pom的profile值带入jsp
- php - 从链接标签中过滤属性,PHP中的href除外
- c++ - C++ 多索引表 - eos 持久性 API
- svg - 标准 svg 字体的字符宽度
- android - Powermock 抱怨在 2 个地方发现了 default.properties 文件
- ios - 通过外部点击 + VoiceOver 模式关闭 iOS 表单模式
- django - 散景模型不存在
- autoit - AutoIt:用 inputBox 的返回值发送左/右键
- r - 从 R 中的 HGVS 格式中分离特定字符串
- python - matplotlib scatter 不能使用时间作为 x 轴?