将库依赖项注入到Django模型中

时间:2018-08-09 20:26:13

标签: python django-models dependency-injection

我有一个Django模型,该模型利用了一些我希望能够覆盖的库。例如,在测试时,我想传递一个模拟,而不是使模型紧密耦合。我可以在python中执行此操作,但是对于我一生来说,我不知道如何使用Django模型执行此操作。这是一个不使用Django的简化示例:

import requests

class APIClient:
  def __init__(self, **kwargs):
    self.http_lib = kwargs.get("http_lib", requests)

  def get_url(self, url):
    return self.http_lib.get(url)

对于此类的常规使用,我仍然可以使用requests,但是如果出于某种原因我想使用其他库或者要测试某些结果,则可以使用client = APIClient(http_lib=MockRequests())来调用该类。

但是我该如何使用Django模型呢?如果我尝试传递数据库字段不支持的kwarg,则Django会引发错误。覆盖__init__也不被认为是一种好习惯。在Django中,有没有一种方法可以设置和获取不受数据库列支持的值?

1 个答案:

答案 0 :(得分:0)

您有一个settings.TEST变量吗?如果是这样,您可以使http_lib的函数返回正确的lib:

from django.conf import settings

def get_http_lib(mock=None):
    if not mock:
        return requests
    return MockRequests()

class APIClient(Model):
    def __init__(self, **kwargs):
        # ...whatever...

    @property
    def some_column(self):
        http_lib = get_http_lib(settings.TEST)
        # ...etc...

不理想,但是可以通过。


PRE-EDIT答复(无效):

如果您在实例化Model之后setattr怎么办?

# In model...
class APIClient(Model):
    def __init__(self, **kwargs):
        self.http_lib = requests
    # ...etc...

# In tests...
client = APIClient()
setattr(client, 'http_lib', MockRequests())