中间件出现问题

问题描述 投票:0回答:1

我想创建一个功能:管理员为讲师创建一个帐户,默认密码是

ou@123
。如果一定时间后(这里我设置为1分钟用于测试),如果讲师没有更改密码,系统将自动锁定帐户(
is_active=False
)。我在
middlewares
views
中编写了处理代码,但出现错误:
django.template.response.ContentNotRenderedError: The response content must be rendered before it can be accessed.

# middlewares.py

class PasswordChangeMiddleware(MiddlewareMixin):
    def process_request(self, request):
        if request.user.is_authenticated and request.user.is_staff:
            if not request.user.password_changed:
                if timezone.now() > request.user.date_joined + timedelta(minutes=1):
                    request.user.is_active = False
                    request.user.save()
        return None

    def process_response(self, request, response):
        if request.user.is_authenticated and not request.user.is_active:
            return Response({"message": "Account Locked"}, status=status.HTTP_403_FORBIDDEN)
        return response

# 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',
    'alumni.middlewares.PasswordChangeMiddleware',
]

# views.py

class UserViewSet(viewsets.ViewSet, generics.CreateAPIView):
    queryset = User.objects.filter(is_active=True)
    serializer_class = serializers.UserSerializer
    parser_classes = [parsers.MultiPartParser, ]

    def get_permissions(self):
        if self.action in ['current_user', 'list_posts', 'get_posts', 'my_post', 'change_password']:
            return [permissions.IsAuthenticated()]
        elif self.action in ['create_lecturer']:
            return [permissions.IsAdminUser()]
        return [permissions.AllowAny()]

    @action(methods=['get', 'patch'], url_path='current-user', detail=False)
    def current_user(self, request):
        user = request.user
        if request.method.__eq__('PATCH'):
            for k, v in request.data.items():
                setattr(user, k, v)  # user.k = v
            user.save()
        return Response(serializers.UserSerializer(user).data)

    @action(methods=['post'], url_path='change-password', detail=False)
    def change_password(self, request):
        user = request.user
        current_password = request.data.get('current_password')
        new_password = request.data.get('new_password')
        confirm_password = request.data.get('confirm_password')

        if user.check_password(current_password):
            if new_password == confirm_password:
                user.set_password(new_password)
                user.password_changed = True
                user.save()
                return Response({"success": "Mật khẩu đã được thay đổi thành công!"})
            else:
                return Response({"error": "Xác nhận mật khẩu không khớp!"}, status=status.HTTP_400_BAD_REQUEST)

        return Response({"error": "Mật khẩu hiện tại không chính xác!"}, status=status.HTTP_400_BAD_REQUEST)

    @action(methods=['post'], url_path='create-lecturer', detail=False)
    def create_lecturer(self, request):
        data = request.data.copy()
        data['password'] = make_password('ou@123')
        data['is_staff'] = True

        serializer = self.serializer_class(data=data)
        if serializer.is_valid():
            user = serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
django-rest-framework middleware
1个回答
0
投票

在 Django REST Framework (DRF) 中,ViewSet 可能会在其视图函数使用的 Response 对象上设置属性。但是,直接在中间件中创建响应时,这些属性可能不存在。所以你应该手动设置它们。

def process_response(self, request, response):
    if request.user.is_authenticated and not request.user.is_active:
        response = Response({"message": "Account Locked"}, status=status.HTTP_403_FORBIDDEN)
        response.accepted_renderer = JSONRenderer()
        response.accepted_media_type = "application/json"
        response.renderer_context = {}
        response.render()
    return response

建议:如果您的

process_request
函数可以返回完整的 HTTP 响应,请考虑在那里创建并返回 403 响应。这样就避免了调用ViewSet的视图函数,提高了效率。

© www.soinside.com 2019 - 2024. All rights reserved.