Oof, this is actually extremely complicated. Dumping my brain for posterity:

1. The reason this is broken is because django-cache-machine does not invalidate objects when M2Ms are changed. This is a [known issue](https://github.com/jbalogh/django-cache-machine/issues/23).
2. As @robhudson noted, it's incorrect to simply use `no_cache` here. That fixes the issue reported in the bug, but leaves potentially-invalid items in the cache that could be returned by other views.
3. You cannot invalidate an M2M by invalidating the items in `obj.field.through.objects.all()`, as they do not inherit from `CachingMixin`.
4. For that reason, django-cache-machine uses caches based on the related objects.
5. That means that, to fix this problem, we should be invalidating this way: `Collection.objects.invalidate(*collection.curators.all())`. This is represented in the (working) patch [here](https://github.com/chuckharmston/zamboni/commit/6ed259d2448ea4bdabef21fb7a3f256c67f96479).
6. That will invalidate all querysets across the site that contain the `UserProfile` objects representing the curators.
7. That is bad; it could potentially be a large number of querysets, some of which may be frequently-accessed or expensive to generate.

Thoughts, anyone?