我正在使用Django 3.2.

我有一个这样的模型:

class MyModel(models.Model):
    last_valid_field_values = models.TextField(help_text='JSON field of fieldnames and values')
    # ...

我希望能够对我的查询进行monkey补丁,这样在获取MyModel个实例时,我可以添加一个属性last_values_dict——这只是last_valid_field_values中加载的JSON.

所以我会有这样的东西(伪代码):

def callback_func(instance):
    instance.last_values_dict = json.loads(instance.last_valid_field_values)
    
    
MyModel.objects.all().apply_some_function_to_monkey_patch(callback_func)

我该怎么做?我还认为,这可能是通过一个遍历QuerySet

推荐答案

您可以将QuerySet子类化以实现apply_some_function_to_monkey_patch,并重写_fetch_all以运行回调函数,类似于QuerySet.prefetch_relatedimplemented.您还需要重写__init___clone以使其与过滤器一起工作.

class MyQuerySet(models.QuerySet):
    def __init__(self, model=None, query=None, using=None, hints=None):
        super().__init__(model=model, query=query, using=using, hints=hints)
        self._callback_funcs = ()
        self._callback_done = False

    def apply_some_function_to_monkey_patch(self, *callback_funcs):
        qs = self._chain()
        qs._callback_funcs = qs._callback_funcs + callback_funcs
        return qs

    def _callback(self):
        for callback_func in self._callback_funcs:
            for item in self._result_cache:
                callback_func(item)
        self._callback_done = True

    def _clone(self):
        clone = super()._clone()
        clone._callback_funcs = self._callback_funcs[:]
        return clone

    def _fetch_all(self):
        super()._fetch_all()
        if self._callback_funcs and not self._callback_done:
            self._callback()

用法:

class MyManager(BaseManager.from_queryset(MyQuerySet)):
    pass


class MyModel(models.Model):
    objects = MyManager()
def callback_func(instance):
    instance.last_values_dict = json.loads(instance.last_valid_field_values)
    
    
MyModel.objects.all().apply_some_function_to_monkey_patch(callback_func)

Python相关问答推荐

无法通过python-jira访问jira工作日志(log)中的 comments

管道冻结和管道卸载

用Python解密Java加密文件

在Python中动态计算范围

matplotlib + python foor loop

跳过嵌套JSON中的级别并转换为Pandas Rame

ConversationalRetrivalChain引发键错误

导入错误:无法导入名称';操作';

如何在海上配对图中使某些标记周围的黑色边框

无法在Spyder上的Pandas中将本地CSV转换为数据帧

如何在FastAPI中替换Pydantic的constr,以便在BaseModel之外使用?'

当HTTP 201响应包含 Big Data 的POST请求时,应该是什么?  

为什么dict. items()可以快速查找?

用来自另一个数据框的列特定标量划分Polars数据框中的每一列,

Regex用于匹配Python中逗号分隔的AWS区域

如果列包含空值,则PANAS查询不起作用

时间戳上的SOAP头签名无效

如何通过特定导入在类中执行Python代码

为什么内置的sorted()对于一个包含降序数字的列表来说,如果每个数字连续出现两次,会变慢?

颂歌中的线性插值法(盖柯)