I took part of this conversation offline to spare the list from the gory details, but the upshot was that verifying an OTP is logically a mutating operation on the verifying device, and thus is not really valid on an unsaved model object. I posted an update to the documentation to clarify.
There were a couple of other questions down there that got lost, but they're more interesting to Django in general. Managing a heterogenous collection of model objects is indeed a little tricky, although it's definitely a solved problem: this is precisely what the admin interface does. Technically, it should be easy to derive an AdminSite that allows a user to manage their own devices, although integrating that cleanly into a broader site design is probably more trouble than it's worth. I suspect that your approach using ContentTypes is a good one--that's pretty much what they're for.
When I first embarked on this project, I actually thought that device management was one of the primary goals. Initially, writing a plugin required not just a model class, but a collection of forms that could be used to create and manage that device. Eventually I decided that there were several good reasons not to go down this road. To take one example, a TOTPDevice is fairly generic and could be paired with any number of real-world provers. Google Authenticator is the main one I know about, but there are others out there and more will emerge. Each prover may have a unique setup flow with different required TOTP parameters, some of which can't be anticipated in advance. For that reason alone, I think that integrating any kind of management UI directly into the device definition is a dangerous layer violation.
I'll back up for a minute and point out that--true to the open-source ethic--one reason I haven't published any generic device management code is that I haven't myself needed it. I currently have django-otp deployed in two places. One is only for internal users ("staff" in Django parlance), so it just uses the management interface. The other is targeted at competent but not necessarily technical users, so it's fairly directed. For example, I require that these users register and confirm an SMS device before I issue backup codes and a Google Authenticator key. This all uses device-specific UI, so no need to be generic.
This gets at the larger issue, which is designing policies for two-factor authentication. The policy that you're proposing is essentially to support as many kinds of OTP devices as you can and let users manage their own security. I think that model has a lot of merits and I'd be happy to see more sites adopt it where appropriate. Of course, the downside to being too casual about two-factor policies is account recovery. I recently read an article in which Google cited this as their Achilles heel in their push for two-factor everywhere. Hence the not-uncommon policy of requiring an SMS backup before allowing more volatile options.
What this all comes down to is that I think there's plenty of room for code that facilitates different kinds of two-factor authentication policies in Django apps. django-otp itself shouldn't include any of them, of course, because it's just the framework that provides the underlying mechanisms. I can easily imagine a django-otp-authenticator app which has tools for generating Google-Authenticator-compatible TOTPDevice objects, rendering QR codes, confirming, etc. Or, at a higher level, django-otp-devices, with views that allow a user to manage their own heterogenous collection of devices. The problem space is quite large and I'm not sure how it all shakes out in the end.
On the decorator question, it occurred to me that I actually use the otp-required-if-configured pattern as well, although I had it implemented directly in a view hierarchy. There seems to be a bit of incoherence in recent Django versions between the decorated-view pattern and the view-as-class pattern. In any case, I expanded the otp_required decorator to take an if_configured argument. New versions of django-otp and django-otp-agents are available.
Thanks so much for your feedback. Do keep in touch either here or privately to let me know how it works out.
Peter