很抱歉,如果您之前已经回答了这个问题,但是已经搜索了几个小时。
我正在尝试对具有m2m字段的Django rest模型进行验证。我有一个分配了角色的模型。如果角色与现有模型重叠并且想抛出验证错误,我有一些逻辑。我已经尝试过pre_save信号,但是显然django直到保存之后才分配m2m(无id)。如何访问数据pre_save?这是模型:
class ActivityFactory (models.Model):
"""
This provides an interval over which ActivityDemands are auto-generated and ActivityStudyHours (note that activity study hours can be obsolete as all of the same information is already stored here) instead of the traditional method of inputing ActivityDemands per month. The product of Activity and ActivityDemand will still create StudySiteWorkloads.
"""
start_date = models.DateField()
end_date = models.DateField()
hours = models.DecimalField(max_digits=5, decimal_places=2)
notes = models.TextField(blank=True, null=True)
activity = models.ForeignKey(Activity, on_delete=models.CASCADE, related_name='activity_factories')
roles = models.ManyToManyField(Role, blank=True, related_name='activity_factories')
study = models.ForeignKey(Study, on_delete=models.CASCADE, related_name="activity_factories")
trend_curve = models.ForeignKey(TrendCurve, on_delete=models.CASCADE, related_name="activity_factories")
slug = AutoSlugField(populate_from='study', db_index=True, unique=True, null=True)
class Meta:
verbose_name_plural = 'Activity Factories'
def __str__(self):
return "%s: %s : %s" % (self.study.study_name, self.activity.activity_name, self.trend_curve.denominator_name)
这是pre_save:
@receiver(pre_save, sender=ActivityFactory)
def validate_factory(sender, instance, **kwargs):
queryset = ActivityFactory.objects.filter(activity=instance.activity, study=instance.study)
roles=instance.roles.objects.all()
for activity_factory in queryset:
if activity_factory.slug!=instance.slug:
if ((activity_factory.start_date <= instance.start_date <= activity_factory.end_date) or (activity_factory.start_date >= instance.end_date >= activity_factory.end_date)) and bool(set(activity_factory.roles.all()) & set(roles)):
raise serializers.ValidationError({'activity':'Date intervals cannot overlap for a given activity in the same study with the same assigned role'}, code=400)
if activity_factory.activity==instance.activity and activity_factory.hours!=instance.hours and bool(set(activity_factory.roles.all()) & set(roles)):
raise serializers.ValidationError({'activity':'The same activity can not have differing hours assigned to the same role within a study. Consider a new activity or keep hours the same'}, code=400)
答案 0 :(得分:0)
想想我可能已经知道了。您可以按以下方式使用m2m_changed信号:
@receiver(m2m_changed, sender=ActivityFactory.roles.through)
def validate_factory_m2m(sender, instance, **kwargs):
queryset = ActivityFactory.objects.filter(activity=instance.activity, study=instance.study)
roles=instance.roles.all()
for activity_factory in queryset:
if activity_factory.slug!=instance.slug:
if ((activity_factory.start_date <= instance.start_date <= activity_factory.end_date) or (activity_factory.start_date >= instance.end_date >= activity_factory.end_date)) and bool(set(activity_factory.roles.all()) & set(roles)):
instance.delete()
raise serializers.ValidationError({'activity':'Date intervals cannot overlap for a given activity with the same assigned role. Consider removing that role or changing the dates or activity'}, code=400)
if activity_factory.activity==instance.activity and activity_factory.hours!=instance.hours and bool(set(activity_factory.roles.all()) & set(roles)):
raise serializers.ValidationError({'activity':'The same activity can not have differing hours assigned to the same role within a study. Consider a new activity or role, or keep hours the same'}, code=400)