Django - ModelChoiceField queryset caching
It would be nice to know a better way to cache the ModelChoiceField’s queryset when it’s used in a form that runs “is_valid()” in a loop (like Formsets do). The best way I know how at the moment is by not using a ModelChoiceField at all. The solution requires using a ChoiceField, running the query for choices outside of the loop, then passing the choices into the form to override the ChoiceField choices.
Here’s an example:
| # See full example: https://github.com/pawl/django_modelchoicefield_caching/blob/master/myapp/views.py#L31-L51 | |
| for song in playlist: | |
| form_data = {'title': song["title"], 'artist': song["artist"]} | |
| song_form = forms.SongFormWithModelChoiceField(data=form_data) | |
| song_form.is_valid() # runs a query to get the ModelChoiceField queryset each time | |
| print('ModelChoiceField - query count AFTER validating all songs:', | |
| len(connection.queries)) # 5 queries | |
| # query for choices outside of the loop to prevent unnecessary queries | |
| artist_choices = [(artist.pk, artist.name) | |
| for artist in models.Artist.objects.all()] | |
| for song in playlist: | |
| form_data = {'title': song["title"], 'artist': song["artist"]} | |
| # pass choices into the Form | |
| song_form = forms.SongFormWithChoiceField( | |
| artist_choices=artist_choices, | |
| data=form_data) | |
| song_form.is_valid() | |
| print('ChoiceField w/ choices passed in - query count AFTER validating all songs:', | |
| len(connection.queries)) # 6 queries (only 1 more query!) |