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
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
This is an exceptional case for my app so I’ve considered using an exception. I’ve considered raising a new exception like
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.