Django 1.11中set_unusable_password与设密码为None的作用疑问
set_unusable_password() in Your Django LDAP Auth Flow Great question—this is one of those subtle Django auth details that can feel confusing when maintaining code from a previous developer. Let’s break down why that call might have been added, and what risks you might face if you remove it, especially in Django 1.11.
First, What Does set_unusable_password() Actually Do?
In Django 1.11, this method sets the user’s password field to a special value (specifically, it starts with the UNUSABLE_PASSWORD_PREFIX, which defaults to !). The key thing here is that Django’s built-in auth system recognizes this value as meaning: "this user cannot authenticate using a local database password".
When you set the password to None instead, the database stores a NULL value in the password column. At first glance, both approaches seem to achieve the same goal—preventing local password login—but there are subtle differences worth noting.
Why Might the Original Developer Have Added This Call?
There are a few plausible reasons:
- Explicit Semantics:
set_unusable_password()is Django’s official, documented way to mark a user as unable to use local password auth. It’s far more readable than settingpassword=None—any future developer looking at the code will immediately understand the intent, whereasNonemight be mistaken for an oversight or bug. - Compatibility with Older Code/Dependencies: If your codebase was upgraded from an earlier Django version (pre-1.11), older releases had different handling for
NULLpasswords. Some versions might not have correctly recognizedNULLas an unusable password, or third-party LDAP libraries you’re using might have expected the officialset_unusable_password()marker to function correctly. - Defensive Coding: Even if
password=Noneworks today, some internal Django methods (likehas_usable_password()) might rely on the explicit marker in edge cases. While in Django 1.11has_usable_password()returnsFalsefor bothNULLpasswords and ones set viaset_unusable_password(), this wasn’t always consistent in older versions. The original dev might have added it to avoid any unexpected behavior.
What Are the Risks of Removing It?
Your tests show it works now, but here’s what to watch out for:
- Future Django Upgrades: If you ever plan to upgrade Django beyond 1.11, newer versions might change how
NULLpasswords are handled.set_unusable_password()is a stable, supported API that’s unlikely to break, whereas relying onNULLcould lead to unexpected auth behavior in newer releases. - Hidden Dependencies: Check if any custom code, middleware, or third-party apps in your project rely on
has_usable_password()or direct checks on thepasswordfield. For example, some admin customizations or user management tools might behave differently if they see aNULLvs. the unusable password marker. - Readability & Maintainability: As mentioned earlier,
set_unusable_password()makes your auth flow’s intent crystal clear. Removing it might leave future developers wondering why the password is set toNone—is that a bug, or intentional?
Final Recommendation
If your tests pass without the call and you’re confident there are no hidden dependencies, you can remove it in your Django 1.11 setup. However, keeping set_unusable_password() is safer in the long run: it aligns with Django’s best practices, improves code readability, and reduces the risk of issues if you ever upgrade or add new auth-related functionality.
Before making the change, do a full audit of your codebase for any references to has_usable_password() or direct checks on the password field to ensure nothing breaks.
内容的提问来源于stack exchange,提问作者Ian Kirkpatrick

