通过相关字段验证Django表单

时间:2014-09-01 13:54:14

标签: python django django-forms

我是Python和django的新手,我在实现模型表单验证方面遇到了麻烦。

我有一个表单,用户可以注册参加多个研讨会。我想验证表单,以便用户无法注册具有重叠时段的研讨会。

我无法确定如何访问进行比较所需的时间数据。

问题:

  1. 如何从Workshop模型访问相关时间数据并按表单输入过滤?
  2. 如何比较此数据将返回的多个项目?
  3. 当我运行下面的代码时,我得到了太多的值来解压缩"错误。我理解为什么会这样,但不知道如何访问数组中的信息以进行比较。

    models.py

    from django.db import models
    from django.contrib.auth.models import User
    
    class Workshop(models.Model):
        title = models.CharField(max_length=100)
        tuition = models.PositiveIntegerField()
        start_time = models.DateTimeField()
        end_time = models.DateTimeField(
    
    class Registration(models.Model):
        user = models.ForeignKey(User)
        workshop = models.ManyToManyField(Workshop)
    

    forms.py

    from django.db import models  
    from django.forms import ModelForm
    from .models import Registration, Workshop
    from django.core.exceptions import ValidationError
    
    
    class RegistrationForm(ModelForm):
        class Meta:
            model = Registration
            exclude = ['user']
    
        def clean(self):
            workshop = self.cleaned_data.get('workshop')
            startTime = Workshop.objects.get('workshop__start_time')
            endTime = Workshop.objects.get('workshop__end_time')
            if (startTime > endTime) or (startTime == startTime): 
                raise ValidationError("Workshop times overlap.")
            return self.cleaned_data  
    

3 个答案:

答案 0 :(得分:1)

首先,概念化不是很明确,对于初学者来说,它不应该被称为RegisteredUsers而不是Registration(动词而不是名词),如果workshop是很多它应该被命名为workshops,因为它保存了多个条目。除此之外,你的问题可以这样解决:

1)在干净的workshop = self.cleaned_data.get('workshop')中,它可以(可能是)向研讨会返回多个值,让我们像这样重命名workshops = self.cleaned_data.get('workshops') 2)迭代workshops,您的查询应检查3种不同类型的重叠,一种是当有问题的工作室完全包含在一个或多个此类用户的此类研讨会中时,第二次是在研讨会开始之后或更多的研讨会,但在他们面前完成,第三次在其他研讨会之前开始,但在一个或多个之后完成,如下:

from django.db.models import Q
    for workshop in workshops:
        if (workshops.filter(Q(start_time__gte=workshop__start_time),Q(end_time__lte=workshop__end_time) |
                             Q(start_time__lte=workshop__start_time),Q(end_time__gte=workshop__start_time)|
                             Q(start_time__lte=workshop__start_time),Q(end_time__gte=workshop__start_time)).count()>1): # count>1 is used because one of the result of filter will be the same workshop object that we are checking against
            #there is an overlap, put your overlap handling code here
        else:
            #there is no overlap, put your saving the data code here

这里唯一的假设是,研讨会是一个查询集而不是列表,如果它的列表通过收集列表中所有研讨会的ID将其转换回查询集,并执行此操作以获取研讨会的查询集:

workshops = Workshop.objects.filter(pk__in=list_of_ids)

答案 1 :(得分:0)

如果每次用户注册时都必须检查重叠,那将是一项繁重的工作。相反,您可以做的是在插入研讨会时检查重叠。然后你可以有一个重叠表来存储重叠的研讨会。通过这种方式,您可以通过在重叠表中检查相同内容来注册两个重叠的研讨会,以警告用户。

答案 2 :(得分:0)

您可以使用django queryset中的lt(小于)或gt(大于)methods。如果存在start_time > workshop.end_timestart_time = workshop.start_time引发错误的研讨会。

 def clean(self):
        workshop = self.cleaned_data.get('workshop')
        overlaping = Workshop.objects.filter('start_time__gt'=workshop.end_time,\
                                     'start_time'=workshop.start_time).exists()
        if overlaping:
              raise ValidationError("Workshop times overlap.") 
        return self.cleaned_data