Проверка django pre_save для полей m2m (многие ко многим)

Извиняюсь, если на этот вопрос уже был дан ответ, но я искал его несколько часов.

Я пытаюсь выполнить проверку модели отдыха django с полем m2m. У меня есть модель, которой назначены роли. У меня есть некоторая логика, если роли перекрываются с существующими моделями и я хотел бы выдать ошибку проверки. Я пробовал сигнал pre_save, но, видимо, django не назначает m2m до тех пор, пока не сохранится (без идентификатора). Как получить доступ к данным 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)

person Bhavesh    schedule 12.11.2018    source источник
comment
Это помогает? docs.djangoproject.com/en/2.1/ref/signals/# m2m-изменено   -  person RHSmith159    schedule 12.11.2018


Ответы (1)


Думаю, я, возможно, понял это. вы можете использовать сигнал 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)
person Bhavesh    schedule 12.11.2018