Предварительная проверка django на полях m2m (много ко многим) - PullRequest
0 голосов
/ 12 ноября 2018

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

Я пытаюсь выполнить проверку на модели отдыха Джанго с полем 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)

Вот предварительное сохранение:

@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)

1 Ответ

0 голосов
/ 12 ноября 2018

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