В Django я хотел бы сузить выбор с помощью формы до другой формы
Я пытаюсь использовать результат селекции в качестве входных данных для другой селекции. Я работаю над этим уже три недели и не могу найти простой ответ.
Вот мои модели:
from django.db import models
# Create your models here.
class School(models.Model):
id = models.CharField(primary_key=True, max_length=10)
school_name = models.CharField(max_length=80)
def __str__(self):
return(f"{self.id} {self.school_name}")
return self.id
class Meta:
ordering = ['id']
indexes = [
models.Index(fields=['id', 'school_name']),
]
class Courses(models.Model):
id = models.CharField(primary_key=True, max_length=12)
created_at = models.DateTimeField(auto_now_add=True)
school = models.ForeignKey(School, on_delete=models.PROTECT, related_name='school')
name = models.CharField(max_length=150, null=True, blank=True)
cost = models.CharField(max_length=75, null=True, blank=True)
class Meta:
ordering = ['id']
indexes = [ models.Index(fields=['school']), models.Index(fields=['name', 'id'])]
def __str__(self):
return(f"{self.school} {self.name}")
return self.name
class Student(models.Model):
course = models.ForeignKey(Courses, on_delete=models.PROTECT)
created_at = models.DateTimeField(auto_now_add=True)
student_id = models.CharField(max_length=20, null=True, blank=True)
class Meta:
ordering = ['course']
indexes = [
models.Index(fields=['course']),
]
А мои взгляды:
def choose_school3(request):
if request.user.is_authenticated:
aschool = Courses.objects.all()
form=SelectSchoolForm(request.POST)
if request.method == "POST":
if form.is_valid():
data = form.cleaned_data
choice = data['school']
selected_school = Courses.objects.filter(school=choice).values()
context = {'choice': choice}
return render(request, 'add_student2b.html', context)
context = {'form': form, 'aschool':aschool}
return render(request, 'choose_school3.html', context)
else:
messages.success(request, "You Must Be Logged In To View Records!")
return redirect('main')
def add_student2b(request, choice):
chosen_school = Courses.objects.filter(school=choice).values()
form = AddStudentForm(request.POST)
context = {'form':form, 'choice':choice, 'chosen_school':chosen_school}
return render(request, 'add_student2b.html', context)
def add_student5(request, pk):
if request.user.is_authenticated:
choice = School.objects.get(id=pk)
courses = Courses.objects.filter(school=choice)
form = modelformset_factory(Student, fields=['course','student_id'], formset=AddStudentForm2FormSet)
context = {'courses':courses, 'choice':choice, 'form':form}
return render(request, 'add_student5.html', context)
else:
messages.success(request, "You Must Be Logged In To View Records!")
return redirect('main')
Формы:
class SelectSchoolForm(forms.ModelForm):
class Meta:
model = Courses
fields = ('school', )
labels = {'school':'School', }
widgets = {'school': forms.Select(attrs={"placeholder":"School", "class":"form-select"}),
}
class AddStudentForm(forms.ModelForm):
class Meta:
model = Student
fields = ( 'student_id', )
labels = {'student_id':'',}
widgets = {'student_id':forms.widgets.TextInput(attrs={"placeholder":"Student ID", "class":"form-control"}),
}
class AddStudentForm2FormSet(BaseModelFormSet):
def __init__(self, *args, **kwargs):
super().__init__(self, *args, **kwargs)
self.fields['course'].queryset = Student.objects.filter(all)
и html: choose_school3.html:
<form class="row g-3" action="{% url 'choose_school3' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="col-md-6">
{{ form.as_p }}
</div>
<div class="col-md-6">
<button type="submit" class="btn btn-secondary">Choose School</button>
<a href="{% url 'school' %}" class="btn btn-success">Back</a>
</div>
</form>
add_student2b.html:
<form class="row g-3" action="{% url 'choose_school' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="col-md-6">
{{ form.as_p }}
</div>
<div class="col-md-6">
<a class="btn btn-secondary btn-lg" href="{% url 'add_student5' choice.id %}" role="button">Add Student</a>
<a href="{% url 'school' %}" class="btn btn-success">Back</a>
</div>
</form>
и add_student5.html:
<form class="row g-3" action="{% url 'choose_school' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="col-md-6">
{{ form.as_p }}
</div>
<div class="col-md-6">
<a class="btn btn-secondary btn-lg" href="{% url 'add_student5' choice.id %}" role="button">Add Student</a>
<a href="{% url 'school' %}" class="btn btn-success">Back</a>
</div>
</form>
Все, что я пытаюсь сделать, приводит к ошибке. Последняя инкарнация дает мне следующее:
невозможно распаковать неитерабельный объект buildin_function_or_method
ссылаясь на тег {{ form.as_p }}. Я хожу по кругу и спускаюсь в кроличьи норы. Возможно ли это сделать с помощью Django (и без JS или других вещей) или нет? Пожалуйста, помогите.
Кавеат: Я не очень понимаю, что вы пытаетесь сделать.
Простой ответ - это просто два отдельных представления, реализующих первый и второй этапы. Валидация первого вызывает перенаправление на второй, который может получать данные из первой формы через kwargs или через базу данных, если прямой доступ ко второй форме должен быть безопасно невозможен.
Более сложным вариантом является форма со скрытыми полями, которые вы динамически преобразуете в не скрытые после того, как первичные поля будут предоставлены и проверены. Можно также преобразовать видимые поля в скрытые, чтобы сохранить их содержимое.
Я всегда использую представления на основе классов и рекомендую это делать всем. Они значительно упрощают логику. В предыдущем случае начальные значения проверяются через форму, но form_valid
затем скрывает скрытые поля и возвращает form_invalid(self, form)
до тех пор, пока не будет предоставлена дополнительная информация.