我有一个具有重写的__init__
方法的模型,如下所示:
class MyModel(models.Model):
...
def __init__(self, *args, **kwargs):
if not kwargs.get('skip', False):
do_something()
super().__init__(*args, **kwargs)
当我执行查询集时,如何将skip
参数传递给__init__
:
data = [obj for obj in MyModel.objects.all()]
我想在自定义管理器中通过方法实现这一点,使用如下所示:queryset.with_skip()
发布于 2017-09-01 15:42:36
我看到,在将参数skip
传递给super().__init__
之前,您不会从kwargs
中删除它。这意味着"skip“是字段的名称,否则就会出现异常TypeError("'skip' is an invalid keyword argument for this function")
。
如果在使用对象之前创建对象时确实需要do_something()
,那么任何人都不应该忘记避免所有不受支持的方式(??)那么,定制经理等等是不够的。
您的问题是,models.Model.__init__(...)
非常完美地支持*args
和**kwargs
参数,因此它们应该是可互换的。您破坏了它,如果“跳过”是通过位置参数的完整元组传递的,则忽略它。也就是说,如果对象是从数据库创建的。读取文档定制模型加载
..。如果模型的所有字段都是存在的,那么就可以保证值按照
__init__()
期望的顺序进行。也就是说,实例可以由cls(*values)
创建. 。| @classmethod
| def from_db(cls, db, field_names, values):
| ...
| instance = cls(*values)
| ...
修复它的一个简单方法是在super().__init__
之后调用super().__init__
并读取self.skip
,而不是实现对kwargs和args的解析。
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if not self.skip:
do_something()
如果需要的话,问题可能是在super().__init__
末尾发送的信号“super().__init__
”。
最后一种可能是支持*args
(hacky,但仍以某种方式使用文档名称):
def __init__(self, *args, **kwargs):
if kwargs:
skip = kwargs.get('skip', False)
else:
# check "val is True" in order to skip if val is DEFERRED
skip = any(field.name == 'skip' and val is True
for val, field in zip(args, self._meta.concrete_fields)
)
if not skip:
do_something()
super().__init__(*args, **kwargs)
编辑:,你可能不需要你想要的东西,而一个代理模型可以做一些额外的事情,有时在同一个数据库表中的相同数据上的一个基本模型是正确的解决方案。("Skip“看起来不是描述对象数据的名称,而是描述对象创建模式的名称。测试和维护子类比内部的神秘开关更容易。)
https://stackoverflow.com/questions/45995549
复制相似问题