Python 如何以及为什么我可以';是否覆盖django上的相关管理器方法?
我有一位经理:Python 如何以及为什么我可以';是否覆盖django上的相关管理器方法?,python,django,orm,entitymanager,Python,Django,Orm,Entitymanager,我有一位经理: class ConfigValueManager(models.Manager): def get(self, key): config_value = self.filter(key=key).first() if config_value: type_caster = locate(config_value.type) return type_caster(config_value.va
class ConfigValueManager(models.Manager):
def get(self, key):
config_value = self.filter(key=key).first()
if config_value:
type_caster = locate(config_value.type)
return type_caster(config_value.value)
return config_value
def set(self, key, value):
self.filter(key=key).update(value=value)
def set2(self, key, value):
qs = self.filter(key=key)
if qs:
qs.update(value=value, type=type(value).__name__, company=self.instance)
else:
self.create(key=key, value=value, type=type(value).__name__, company=self.instance)
问题是我无法覆盖set
。该方法仍然来自父级,即使我已经在子级上创建了set
。有趣的是get
和set2
都很好。即使是我的示例中没有的add
,也不能被覆盖
我的问题是如何覆盖set
以及为什么会发生这种情况?models.py
tests.py
github示例
我补充了一些细节,说明为什么不容易做到这一点,因为我在同一个问题上遇到了困难。
set
,如add
或create
,在动态创建的RelatedManager
中被覆盖,如中所示。这个RelatedManager
实际上将我们的管理器用作一个函数,这就是为什么可以使用get
和set2
方法,但它对重写的方法没有帮助
此管理器是在reverseManalyToneDescriptor.related\u manager\u cls
cached属性中创建的。在github代码段的示例中,Company.config\u values
是此ReverseMayTooneDescriptor
的一个实例
我将展示一个示例,说明如何通过对代码进行一些假设来覆盖set
方法,因为它缺少一些定义(例如Company
模型,FooConfigValue
中的ForeignKey
字段)
我不建议使用它,因为它对django更改绝对不健壮,而且我没有做任何测试,它只是用来证明如何创建RelatedManager
实例
在示例代码的末尾添加这个,它应该可以工作
def修改相关的管理器集(模型cls):
#这里的model_cls=Company,config_value是相关的字段名
反向\u描述符=模型\u cls.config\u值
基本集=反向描述符相关管理器集
def自定义设置(*args,**kwargs):
打印(“在我的自定义集中”)
返回基本设置(*args,**kwargs)
反向\u描述符.相关\u管理器\u cls.set=自定义\u集合
#在创建所有模型后执行此调用
#例如,在定义FooConfigValue之后
修改相关的经理集合(公司)
现在您应该可以看到正在打印我的自定义设置中的
我知道这没有多大帮助,但至少它有助于理解相关字段是如何工作的您是如何使用它的?你到底看到了什么行为?基本管理器类没有set
方法。是的,它有:基本管理类没有set2
,我可以定义它,这无关紧要。我只是想定义一些方法,但其中有些方法似乎有一个约束,我无法覆盖它们。但这就是为什么我问你如何使用它。这是一个相关的管理器,它是动态构建的,而不是一个标准的管理器。再说一次,你是如何在课堂上使用这个的?@Dainel Roseman,像这样:
from django.db import models
from django.db.models.query import QuerySet
class PersonQuerySet(QuerySet):
def set(self, slug, **kwargs):
return self.filter(slug=slug).update(**kwargs)
class Person(models.Model):
name = models.CharField(max_length=100, null=True)
slug = models.CharField(max_length=10, null=True)
objects = PersonQuerySet.as_manager()
from django.test import TestCase
from core.models import Person
class TestSet(TestCase):
def test_just_update_records_with_the_same_slug(self):
Person.objects.create(slug='batman', name='John')
Person.objects.create(slug='batman', name='Connor')
Person.objects.create(slug='bruce', name='Ill be back')
Person.objects.set('batman', name='###')
expected_value = 2
result = Person.objects.filter(name='###').count()
self.assertEqual(result, expected_value)