Django中出现'function' object has no attribute 'user'错误求解决
Django中间件报错:'function' object has no attribute 'user'
问题场景
基于AbstractUser扩展CustomUser模型实现Admin、NotesUser两种角色,配置了LoginCheckMiddleWare权限校验中间件后,访问登录页面触发错误:'function' object has no attribute 'user'。
相关代码
models.py
class CustomUser(AbstractUser): user_type_choices = ((1, "Admin"), (2, "NotesUser")) user_type = models.CharField(max_length=10, choices=user_type_choices, default=1) class Admin(models.Model): user_id = models.OneToOneField(CustomUser, on_delete=models.CASCADE) class NotesUser(models.Model): user_id = models.OneToOneField(CustomUser, on_delete=models.CASCADE) @receiver(post_save, sender=CustomUser) def create_user_profile(sender, created, instance, **kwargs): if created: if instance.user_type == 1: Admin.objects.create(user_id=instance) if instance.user_type == 2: NotesUser.objects.create(user_id=instance) @receiver(post_save, sender=CustomUser) def save_user_profile(sender, instance, **kwargs): if instance.user_type == 1: instance.admin.save() if instance.user_type == 2: instance.notesuser.save()
LoginCheckMiddleWare.py
from django.utils.deprecation import MiddlewareMixin from django.urls import reverse from django.http import HttpResponseRedirect, HttpResponse class LoginCheckMiddleWare(MiddlewareMixin): def process_view(self, view_func, request, view_args, view_kwargs): modulename=view_func.__module__ user = request.user if user.is_authenticated: if user.user_type == "1": if modulename == "todo_app.views" or modulename == "todo_app.AdminViews": pass else: return HttpResponseRedirect(reverse("admin_home")) elif user.user_type == "2": if modulename == "todo_app.UserViews" or modulename == "todo_app.views": pass else: return HttpResponseRedirect(reverse("user_home")) else: pass #return HttpResponseRedirect(reverse("log_in")) else: if request.path == reverse("log_in") or request.path == reverse("login_save") or modulename == "django.contrib.auth.views" or modulename == "todo_app.views": pass else: return HttpResponseRedirect(reverse("log_in"))
settings.py
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'todo_app.LoginCheckMiddleWare.LoginCheckMiddleWare', ]
错误原因
核心问题是中间件process_view方法的参数顺序写错了:
Django规定process_view的正确参数顺序为(self, request, view_func, view_args, view_kwargs),但你把view_func和request的位置写反了。这导致代码中user = request.user实际上是在访问视图函数对象的user属性,而视图函数没有该属性,因此抛出'function' object has no attribute 'user'错误。
解决步骤
1. 修正中间件参数顺序
将LoginCheckMiddleWare.py中的process_view方法参数调整为正确顺序:
def process_view(self, request, view_func, view_args, view_kwargs):
2. 额外修复与优化
- 修复用户类型判断的类型不匹配:
CustomUser中user_type是CharField,但信号处理代码中用整数1/2判断会导致逻辑失效,需要统一改为字符串判断:
或者直接把# 信号处理函数中修改判断条件 if instance.user_type == "1": Admin.objects.create(user_id=instance) if instance.user_type == "2": NotesUser.objects.create(user_id=instance)user_type_choices的键改为字符串,从根源避免类型混淆:user_type_choices = (("1", "Admin"), ("2", "NotesUser")) - 简化中间件逻辑:
将允许访问的模块/路径整理为列表,用in判断替代多个or,提升代码可读性:# 修正后的完整中间件代码 from django.utils.deprecation import MiddlewareMixin from django.urls import reverse from django.http import HttpResponseRedirect class LoginCheckMiddleWare(MiddlewareMixin): def process_view(self, request, view_func, view_args, view_kwargs): modulename = view_func.__module__ user = request.user if user.is_authenticated: if user.user_type == "1": allowed_modules = ["todo_app.views", "todo_app.AdminViews"] if modulename not in allowed_modules: return HttpResponseRedirect(reverse("admin_home")) elif user.user_type == "2": allowed_modules = ["todo_app.UserViews", "todo_app.views"] if modulename not in allowed_modules: return HttpResponseRedirect(reverse("user_home")) else: allowed_paths = [reverse("log_in"), reverse("login_save")] allowed_modules = ["django.contrib.auth.views", "todo_app.views"] if request.path not in allowed_paths and modulename not in allowed_modules: return HttpResponseRedirect(reverse("log_in"))
内容的提问来源于stack exchange,提问作者vishnu chandran
相关产品推荐
相关产品推荐

