Django中如何子类化或补丁AuthenticationMiddleware的用户查询逻辑
解决方案
方法一:自定义认证后端(推荐)
通过子类化ModelBackend并重写get_user方法,这是Django官方推荐的扩展方式,无侵入性且可维护性强。
- 在你的应用目录下创建
backends.py文件,编写自定义后端类:
from django.contrib.auth.backends import ModelBackend from django.contrib.auth import get_user_model class CustomUserModelBackend(ModelBackend): def get_user(self, user_id): try: # 添加select_related预加载关联的Visitor模型 return get_user_model().objects.select_related('visitor').get(pk=user_id) except get_user_model().DoesNotExist: return None
- 在项目的
settings.py中配置认证后端为自定义类:
AUTHENTICATION_BACKENDS = [ 'your_app_name.backends.CustomUserModelBackend', # 若需保留默认后端(如admin登录),可追加原后端路径: # 'django.contrib.auth.backends.ModelBackend', ]
方法二:猴子补丁(快速临时方案)
如果不想修改认证后端配置,可通过猴子补丁直接替换ModelBackend的get_user方法,适合快速验证或临时场景。
- 在应用的
apps.py中修改AppConfig的ready方法:
from django.apps import AppConfig from django.contrib.auth.backends import ModelBackend from django.contrib.auth import get_user_model # 定义补丁后的get_user方法 def patched_get_user(self, user_id): try: return get_user_model().objects.select_related('visitor').get(pk=user_id) except get_user_model().DoesNotExist: return None class YourAppConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = 'your_app_name' def ready(self): # 保存原始方法(可选,用于后续恢复) ModelBackend._original_get_user = ModelBackend.get_user # 替换为自定义方法 ModelBackend.get_user = patched_get_user
- 确保
settings.py的INSTALLED_APPS中使用该AppConfig:
INSTALLED_APPS = [ # ... 'your_app_name.apps.YourAppConfig', # ... ]
注意事项
- 两种方法都能实现一次查询同时获取
User和Visitor数据,彻底解决两次查询的问题。 - 自定义认证后端更符合Django的扩展规范,优先推荐;猴子补丁虽快捷,但需注意Django版本更新可能带来的兼容性风险。
内容的提问来源于stack exchange,提问作者T-101
相关产品推荐
相关产品推荐

