python - 更改数据的 Django 自定义管理器方法无法与其他管理器方法(过滤器、获取等)一起使用

标签 python django django-models django-managers

我创建了一个自定义 Manager,但在我的例子中,它的方法将一些字符串添加到模型中特定字段的末尾,而不是像通常情况下那样仅过滤查询集。

我的目标是在调用 SomeModel.objects 时返回已更改的对象。 Django 的文档说:

You can override a Manager’s base QuerySet by overriding the Manager.get_queryset() method. get_queryset() should return a QuerySet with the properties you require.

当我调用 SomeModel.objects.all() 时,我的方法有效,但如果我为 objects 应用一些过滤器或在 .all() 之后 我可以看到数据变得正常。

模型.py:

class BaseModelQuerySet(models.QuerySet):
    def edit_desc(self, string):
        if self.exists():
            for obj in self:
                if 'description' in obj.__dict__:
                    obj.__dict__['description'] += string
        return self

class BaseModelManager(models.Manager):
    def get_queryset(self):
        return BaseModelQuerySet(self.model, using=self._db).edit_desc('...extra text')


class BaseModel(models.Model):
   objects = BaseModelManager()

    class Meta:
        abstract = True

外壳输出:

>>> Macro.objects.all()[0].description
'Test text...extra text'
>>> Macro.objects.all().filter(id=1)[0].description
'Test text'

这让我很困惑。这样的印象是其他方法调用常规查询集而不是返回自定义 对象

最佳答案

返回查询集的查询集方法实际上返回一个查询集(它们不会就地更改当前查询集)。这并不是说它们返回的是“常规”查询集,它们是您的自定义查询集子类的实例(您可以通过检查您的查询集类型自行检查),但是尚未调用 edit_desc() 方法在他们身上。

从技术上讲,您可以通过覆盖所有排除/过滤/ect 方法以重新应用您的 edit_desc() 方法来“解决”这个问题,但它的效率会非常低(甚至比实际情况还要低),因此您可能需要重新考虑您的真正问题是什么,以及如何以更有效和更少干扰的方式解决它。也许解释您的具体用例可以更好地解决问题 ?

编辑:根据您的评论,一个可能(并且更有效)的解决方案是覆盖产生或返回模型实例(或仅原始值)的 QuerySet 部分,以便您可以处理此时您的模型实例/数据。您可能想看看 django/db/query.py,特别是 ModelIterableValueIterable 类。这比您当前的解决方案要多得多,但是...

如果您只关心模型实例(而不是原始数据),另一个可能更简单的解决方案是使用 ModelProxy,重写它的 __init__ 方法以在此处添加您的处理点……

关于python - 更改数据的 Django 自定义管理器方法无法与其他管理器方法(过滤器、获取等)一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47925776/

相关文章:

python - 计算 Pandas 数据框列组合之间距离的有效方法

python - POST 或 GET 失败或成功时友好的返回消息

Django站点地图更改基本网址

django - Django:是否可以在一个通用 View 中验证和保存多种形式的字段?

python-3.x - DRF ModelSerializer 使所有字段只读,而无需明确指定它们

python - 返回 Python 中的封闭范围变量

python - 卡在这个错误 "RuntimeError: Expected all tensors to be on the same device, but found at least two devices, cuda:0 and cpu"

django - 可选的ImageField(Django)

python - 将数据框的列 append 到 pandas 中的不同数据框

Django - 模型中的自定义保存方法