对 m2m(多对多)字段的 django pre_save 验证

标签 django validation save many-to-many m2m

如果之前已经回答过这个问题但已经搜索了几个小时,我们深表歉意。

我正在尝试对带有 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)

最佳答案

我想我可能已经弄明白了。您可以按如下方式使用 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)

关于对 m2m(多对多)字段的 django pre_save 验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53266557/

相关文章:

python - 组合表单和 model_formset 出现 NoReverseMatch 错误

Django rest_framework 自定义错误信息

java - 如何使用 Java 根据 wml.xsd 验证 Word 2007 文件?

Java swing 在关闭时保存选项卡

java - 在应用程序中保存数据

python - Django:异常值(2013, '2013: Lost connection to MySQL server during query',无)

python - while循环在django中递增范围

objective-c - 带有内置验证的 NSTextField

java - 自定义 validator 和@interface列表

php - 在没有数据库的情况下永久保存 php 变量