Hey, all! I hit an interesting design choice on my Twitch stream this evening related to Class Based Views, and I wanted to check if anyone has alternative patterns to the solution I arrived at.
I have a CreateView
that creates records for a Course
model. The form class that I’m using needs a QuerySet
that is dynamically set when the form is created. Here’s the whole form for context:
class CourseForm(DaysOfWeekModelForm):
class Meta:
model = Course
fields = ["name", "grade_levels"] + DaysOfWeekModelForm.days_of_week_fields
grade_levels = forms.ModelMultipleChoiceField(queryset=GradeLevel.objects.none())
def __init__(self, school_year, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["grade_levels"].queryset = GradeLevel.objects.filter(
school_year=school_year
)
In my view, I need to provide an appropriate school_year
record, which I do in get_form_kwargs
.
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs["school_year"] = SchoolYear.get_current_year_for(self.request.user)
return kwargs
My challenge is this: SchoolYear.get_current_year_for
may return None
. When the value is None
, I don’t want the page to 404. Ideally, it would redirect to a page where a user can create a school year.
The problem is that, to my knowledge, there isn’t a great way to trigger a redirect from the get_form_kwargs
method.
This is an exceptional case for my app so I’ve considered using an exception. I’ve considered raising a new exception like NoSchoolYearError
in get_form_kwargs
and handling that exception in dispatch
to do the redirect.
Generalized, I think my question is this: is there an appropriate hook in CBVs to use to check on form data preconditions before a form is instantiated?
If you’ve got other ideas or I’m missing something obvious about CBVs, I’d love to read your thoughts. Thanks.