I see.  Simple answer:  I don't believe creating another encapsulating layer for this functionality is necessary.  There isn't any state to be kept / generated in that additional capsule, and 1/2 the functionality is in the models anyway, so this kept the view as simple as possible (and somewhat less magical, though I can see that `course_modes.urls` isn't too bad either).  Also, some of django.contrib's views (like auth) structure the code this way.

FWIW, I don't think the if clauses on request.method are too confusing since the clause bodies weren't that long.

I can see a case for a generic model-based view that generates CSVs from model(s) being DRY, but I didn't want to sign up to do that with this feature request.