#django #forms #limit
Вопрос:
Поэтому я хочу установить ограничение на количество форм с одинаковым значением. Существуют различные виды деятельности, отличные от иностранной модели, к которым студенты могут обратиться. У меня есть имя(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' )
Если вы знаете, как решить эту проблему, или у вас есть лучшая идея создания такой системы, пожалуйста, дайте мне знать. Заранее спасибо!!
Ответ №1:
Вероятно, вам понадобится переменная внутри вашего Aktiviteit
класса, например, plaatsen_beschikbaar
которая инициализируется в 10 при создании нового экземпляра an Aktiviteit
. Затем при успешном Aanmelden
переходе к экземпляру вы уменьшаете его на единицу. Вам нужно убедиться, что в вашей модели это plaatsen_beschikbaar
не может быть меньше нуля, и если кто-то удалит aanmelding, увеличьте переменную на 1. Изменить: или вы используете валидатор, подобный приведенному ниже, для ограничения доступа. Вы также можете сделать так, чтобы ваша модель имела свойство@, которое возвращает значение plaatsen_beschikbaar
вместо использования поля. С другой стороны, это кажется лучшим планом, поэтому это редактирование
Чтобы убедиться , что у ученика может быть только 1 Aanmelden
, вы можете просто сделать свой studentnummer
уникальный в своем Aanmelden
классе. Но это делает вашу модель неуязвимой для будущего, если в будущем вы решите, что студенты могут подписаться на два или три мероприятия. В этом случае вам необходимо иметь отношение к внешнему ключу Student
и ограничить его количество Aanmelden
, которое может быть у учащегося, например, с помощью валидатора, подобного этому
def beperk_aanmelden(value): if Aanmelden.objects.filter(student_id=value).count() gt;= 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() gt;= 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 lt;= 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
, что дает вам вычисляемое поле, не относящееся к бд, к которому вы можете получить доступ точно так же, как к обычному полю. Разница в том, что он не сохраняется, а пересчитывается каждый раз, когда вы обращаетесь к нему. Внутри подсчитайте количество экземпляров Aanmelden
, имеющих Activiteit
экземпляр в качестве связанного объекта. Это ваш номер уже забронированного места. Затем вычтите это из 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}"
Комментарии:
1. Эй, первый вариант работает идеально, но у меня возникли некоторые проблемы с применением второго, потому что у меня нет класса для студентов. Как я мог создать студенческий класс и при этом включить его в ту же форму, что и Aanmelden? идея заключается в том, что люди анонимно заходят на сайт, заполняют форму и попадают в группу активности.
2. @enmanuel-v I Валидатор также должен работать для целого числа
studentnummer=value
в валидаторе, а затем в моделиstudentnummer = Integerfield(validators=[beperk_aanmelden,])
3. @Enmanuel-V обновил мой ответ
4. @Enmanuel-V Извините, я только что понял, что забыл добавить
return
функцию проверки в свой первоначальный ответ. Прошу прощения! Я просто поправил.5. Затем вам придется провести некоторую отладку. К сожалению, я в постели с ковидом и отвечаю тебе по памяти на мобильный телефон, лол. Проверьте
plaatsen_beschikbaar
, возвращает ли оно правильное значение. Возможно, валидатор не совсем работает? Вместо проверки поля с помощью валидатора вы также можете легко сделать это внутриclean(self)
метода вашейAanmelden
модели, что проще для понимания. Посмотрите на документы, которые я ссылал выше. Внутриclean(self)
вы проверяете, достаточно ли plaatsen_beschikbaar, и вызываете ошибку проверки, если ее нет.