【问题标题】:Set a limit for forms with the same value Django为具有相同值 Django 的表单设置限制
【发布时间】:2021-12-25 10:25:46
【问题描述】:

所以我想做的是设置具有相同值的表单的限制。学生可以申请与外国模式不同的活动。 我有姓名(naam)、学号(studentnummer)、活动(activiteit)和班级(klas),我想设置一个限制为 10 个具有相同活动的表格(最多可以做相同活动的人)和一个学生人数限制为 1(因此学生只能申请一项活动)。

models.py

class Klas(models.Model):
    klas = models.CharField(max_length=8)

    def __str__(self):
        return f"{self.klas}"
    
class Activiteit(models.Model):
    titel = CharField(max_length=64)
    docent = CharField(max_length=32)
    icon = models.ImageField()
    uitleg = models.TextField()

    def __str__(self):
        return f"{self.id}:{self.titel}:{self.docent}"
    
class Aanmelden(models.Model):
    naam = CharField(max_length=32)
    studentnummer = IntegerField()
    klas = ForeignKey(Klas, on_delete=models.CASCADE, default=None, blank=True)
    activiteit = ForeignKey(Activiteit, on_delete=models.CASCADE, default=None, blank=True)

    def __str__(self):
        return f"{self.id}:{self.naam}:{self.studentnummer}"
 

views.py

def home(request):
   activiteiten = Activiteit.objects.all()
   
   form = AanmeldenForm()
   if request.method == 'POST':
       form = AanmeldenForm(request.POST)
       if form.is_valid():
           form.save()
           
   return render(request, 'home.html', {
       'activiteiten': activiteiten,
       'form':form,
   })

forms.py

class AanmeldenForm(forms.ModelForm):
   class Meta:
       model = Aanmelden
       fields = (
           'naam','studentnummer','klas','activiteit'
       )

如果你知道如何解决这个问题或者对做这种系统有更好的想法,请告诉我。 提前致谢!

【问题讨论】:

    标签: django forms limit


    【解决方案1】:

    您可能需要在Aktiviteit 类中包含一个变量,例如plaatsen_beschikbaar,当您创建Aktiviteit 的新实例时,该变量在10 处初始化。然后在成功的Aanmelden 到一个实例,你将它减少一个。您需要确保在您的模型中plaatsen_beschikbaar 不能小于零,如果有人删除了 aanmelding,则将变量增加 1。编辑:或者您使用如下验证器来限制 Aanmelden。您还可以使您的模型具有返回 plaatsen_beschikbaar 而不是使用字段的 @property。再三考虑,这似乎是一个更好的计划,因此进行了此编辑

    为了确保一个学生可能只有 1 个 Aanmelden,您可以让您的 studentnummer 在您的 Aanmelden 班级中唯一。但是,如果您决定将来学生可以订阅两个或三个活动,那么这会使您的模型无法适应未来。在这种情况下,您需要与Student 建立外键关系,并限制学生使用验证器可能拥有的Aanmelden 的数量,例如

    def beperk_aanmelden(value):
        if Aanmelden.objects.filter(student_id=value).count() >= 1:
            raise ValidationError('Student heeft al de maximale aanmeldingen')
        else:
            return value
    

    然后在您的Aanmelden 模型中:

    student = ForeignKey(Student, validators=[beperk_aanmelden,])
    

    编辑:根据您当前的模型,它看起来像这样:

    def beperk_aanmelden(value):
        if Aanmelden.objects.filter(studentnummer=value).count() >= 1:
            raise ValidationError('Student heeft al de maximale aanmeldingen')
        else:
            return value
    

    在你的模型中:

    studentnummer = IntegerField(validators=[beperk_aanmelden,])
    

    编辑 2:

    要检查plaatsen_beschikbaar,您可以执行以下操作:

    def beperk_activiteit(value):
        if Activiteit.objects.get(activiteit_id=value).plaatsen_beschikbaar <= 0:
            raise ValidationError('Activiteit heeft geen plaatsen beschikbaar meer! Kies een andere activiteit.')
    

    那么对于模型中的字段:

    activiteit = ForeignKey(Activiteit, on_delete=models.CASCADE, default=None, blank=True, validators=[beperk_activiteit,])
    

    编辑 3:

    对于plaatsen_beschikbaar,我会做这样的事情。每个Activiteit 都有一个capaciteit,您可以在其中设置最大可用位置。然后定义一个@property,它为您提供了一个非数据库计算字段,您可以像访问普通字段一样访问该字段。不同之处在于它不会被存储,而是在您每次访问时重新计算。内部计算将Activiteit 实例作为相关对象的Aanmelden 的数量。这是您已经预订的数量。然后从capaciteit 中减去它,你将得到一个当前的plaatsen_beschikbaar

    class Activiteit(models.Model):
        titel = CharField(max_length=64)
        docent = CharField(max_length=32)
        icon = models.ImageField()
        uitleg = models.TextField()
        capaciteit = models.IntegerField()
    
        @property
        def plaatsen_beschikbaar(self):
            geboekt = Aanmelden.objects.filter(activiteit_id=self.id).count()
            return self.capaciteit - geboekt
    
        def __str__(self):
            return f"{self.id}:{self.titel}:{self.docent}"
    

    【讨论】:

    • 嘿,第一个效果很好,但我在申请第二个时遇到了一些麻烦,因为我没有学生课程。我怎样才能创建一个学生类并仍然以与 Aanmelden 相同的形式包含它?这个想法是人们匿名进入网站,填写表格并进入活动组。
    • @enmanuel-v I 验证器也应该适用于验证器中的整数studentnummer=value,然后是模型studentnummer = Integerfield(validators=[beperk_aanmelden,])
    • @Enmanuel-V 更新了我的答案
    • @Enmanuel-V 对不起,我刚刚意识到我忘记在我原来的答案的验证器函数中添加return。道歉!我刚刚更正了。
    • 那么你将不得不做一些调试。不幸的是,我和covid在床上,我正在用手机记忆回复你,哈哈。检查plaatsen_beschikbaar 是否返回正确的值。也许验证器不太工作?除了使用验证器验证字段之外,您还可以轻松地在 Aanmelden 模型的 clean(self) 方法中执行此操作,这更容易理解。查看我上面链接的文档。在clean(self) 中检查是否有足够的 plaatsen_beschikbaar 并在没有时引发验证错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-16
    • 1970-01-01
    • 2011-08-09
    • 1970-01-01
    • 1970-01-01
    • 2017-08-19
    • 2023-04-04
    相关资源
    最近更新 更多