Hi Bruce,
I believe what you're looking for is the if_configured argument to the otp_required decorator.[1][2] Using this approach, you would define a view like the following (or do the equivalent in a base class, if you have a class-based view hierarchy):
@login_required
@otp_required(if_configured=True)
def some_view(request):
...
When an unauthenticated user visits the view, they'll hit login_required and get redirected to the login URL, where they'll presumably authenticate with username and password. They'll then be sent back and hit otp_required. If they have no devices configured, they'll sail past and get to the view. Otherwise, they'll get redirected to OTP_LOGIN_URL, which can be connected to django_otp.views.login or your own equivalent.
From your question, it sounds like you may be trying to limit users at the authentication stage rather than authorization. In other words, for any user with a configured device, you're looking for all or nothing: either anonymous or authenticated+verified. There's no direct support for this, although it's not impossible. The one-stop AuthentiationForm[3] almost does this, it just doesn't happen to have an if_configured option. You could probably use that as a starting point, if that's what you're after.
My recommendation would be the first approach, though. It feels like less of a subversion of Django's authentication design and I think it makes for a better user experience. Your mileage may vary.