You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Python Django中实现SOLID依赖倒置原则时遇TypeError求助

问题描述

我正尝试在Python-Django中实现SOLID原则里的依赖倒置原则,目前遇到如下错误:

TypeError: SignInView.init() missing 1 required positional argument: 'api_response_factory'

我尝试使用抽象方法但未能成功,作为SOLID实现和Python的新手,希望有人能给出解决这类错误的建议或思路。另外,这是我第一次在Stack Overflow提问。

相关代码如下:

from abc import ABC, abstractmethod
from rest_framework.views import APIView
from django.http import JsonResponse
from rest_framework import status

class ApiResponseFactoryAbstract(ABC):
    @abstractmethod
    def success(self) -> str:
        pass

class ApiResponseFactory(ApiResponseFactoryAbstract):
    def success(self) -> str:
        print("Testing")
        return "Testing"

class SignInView(APIView):
    def __init__(self, api_response_factory: ApiResponseFactoryAbstract):
        self.api_response_factory = api_response_factory

    def post(self, request):
        data = self.api_response_factory.success()
        return JsonResponse(data=data, status=status.HTTP_200_OK)

app/urls.py内容:

from django.urls import path
from . import views

router_auth = [
    path("sign-in/", views.SignInView.as_view(), name="sign-in"),
]

错误原因与解决方案

错误的核心是:Django REST Framework的APIView通过as_view()实例化时,不会自动传入你自定义的构造函数参数,且你重写__init__时未兼容父类的初始化逻辑。以下是几种适配Django场景的依赖注入方案:

方案1:给构造函数参数添加默认值(快速解决)

给api_response_factory设置默认实例,同时必须调用父类构造函数,保证APIView的初始化逻辑正常运行:

class SignInView(APIView):
    def __init__(self, api_response_factory: ApiResponseFactoryAbstract = ApiResponseFactory()):
        super().__init__()  # 务必调用父类构造
        self.api_response_factory = api_response_factory

    def post(self, request):
        data = self.api_response_factory.success()
        return JsonResponse(data=data, status=status.HTTP_200_OK)

方案2:使用类属性注入(易测试易扩展)

把依赖定义为类属性,既符合DRF视图的使用习惯,又能在测试时灵活替换实现:

class SignInView(APIView):
    # 默认注入实现,测试时可直接替换
    api_response_factory: ApiResponseFactoryAbstract = ApiResponseFactory()

    def post(self, request):
        data = self.api_response_factory.success()
        return JsonResponse(data=data, status=status.HTTP_200_OK)

测试替换示例:

# 测试用的Mock实现
class MockResponseFactory(ApiResponseFactoryAbstract):
    def success(self) -> str:
        return "Mocked Success"

# 替换视图的依赖
SignInView.api_response_factory = MockResponseFactory()

方案3:使用DRF官方推荐的setup方法(最优解)

DRF视图提供了setup方法用于初始化实例,这是官方推荐的扩展初始化逻辑的方式,避免重写__init__带来的兼容问题:

class SignInView(APIView):
    def setup(self, request, *args, **kwargs):
        super().setup(request, *args, **kwargs)
        # 这里可以灵活注入依赖,比如从配置/DI容器中获取
        self.api_response_factory = ApiResponseFactory()

    def post(self, request):
        data = self.api_response_factory.success()
        return JsonResponse(data=data, status=status.HTTP_200_OK)

如果后续引入第三方DI库(如dependency-injector),可直接在setup中从容器获取实例,进一步解耦。


依赖倒置原则优化提示

你当前的抽象类定义是合格的,但可以让它更贴合API场景:比如把success方法的返回值改为字典,更适配JsonResponse的需求:

class ApiResponseFactoryAbstract(ABC):
    @abstractmethod
    def success(self, data=None) -> dict:
        pass

class ApiResponseFactory(ApiResponseFactoryAbstract):
    def success(self, data=None) -> dict:
        response = {"status": "success", "data": data or {}}
        print(response)
        return response

内容的提问来源于stack exchange,提问作者Sergio Andres Cortes Romero

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 23:35:12