使用参数创建 django 管理器
Creating a django manager with a parameter
我有以下情况
我有一个管理器 class,它根据字段过滤查询集。问题是根据 class 字段名称不同,但它过滤的值来自同一个地方(所以我认为我不需要多个管理器)。这是我到目前为止所做的。
class MyManager(models.Manager):
def __init__(self, field_name):
super(MyManager, self).__init__()
self.field_name = field_name
def get_queryset(self):
# getting some value
kwargs = { self.field_name: some_value }
return super(MyManager, self).get_queryset().filter(**kwargs)
class A:
# some datamembers
@property
def children(self):
return MyUtils.prepare(self.b_set.all())
class B:
objects = MyManager(field_name='my_field_name')
a = models.ForeignKey(A, null=False, blank=False)
当我 运行 测试我从数据库中检索一个 B 对象,并尝试读取 children
属性 我得到以下错误:
self = <django.db.models.fields.related_descriptors.RelatedManager object at 0x7f384d199290>, instance = <A: A object>
def __init__(self, instance):
> super(RelatedManager, self).__init__()
E TypeError: __init__() takes exactly 2 arguments (1 given)
我知道它是因为构造函数参数,因为当我删除它(或给它一个默认值)时,所有测试都有效。
我怎样才能克服这个?这是实现此目标的正确方法吗?
技术资料:
- Django 1.9.5
- 测试框架py.test 2.9.1
谢谢
如您所见,发生该错误是因为每当您调用相关对象时,Django 都会实例化一个新的管理器;该实例化不会获得额外的参数。
与其以这种方式获取值,不如尝试将其设为模型的属性,然后通过 self.model
.
引用它
class MyManager(models.Manager):
def get_queryset(self):
# getting some value
kwargs = { self.model.manager_field_name: some_value }
class B:
manager_field_name = 'my_field_name'
objects = MyManager()
另一种选择是动态生成管理器class,例如:
def manager_factory(custom_field):
class MyManager(models.Manager):
my_field = custom_field
def get_queryset(self):
# getting some value
kwargs = {self.my_field: 'some-value'}
return super(MyManager, self).get_queryset().filter(**kwargs)
return MyManager()
class MyModel(models.Model):
objects = manager_factory('custom_field')
这样您就可以将管理器与模型分离 class。
我有以下情况
我有一个管理器 class,它根据字段过滤查询集。问题是根据 class 字段名称不同,但它过滤的值来自同一个地方(所以我认为我不需要多个管理器)。这是我到目前为止所做的。
class MyManager(models.Manager):
def __init__(self, field_name):
super(MyManager, self).__init__()
self.field_name = field_name
def get_queryset(self):
# getting some value
kwargs = { self.field_name: some_value }
return super(MyManager, self).get_queryset().filter(**kwargs)
class A:
# some datamembers
@property
def children(self):
return MyUtils.prepare(self.b_set.all())
class B:
objects = MyManager(field_name='my_field_name')
a = models.ForeignKey(A, null=False, blank=False)
当我 运行 测试我从数据库中检索一个 B 对象,并尝试读取 children
属性 我得到以下错误:
self = <django.db.models.fields.related_descriptors.RelatedManager object at 0x7f384d199290>, instance = <A: A object>
def __init__(self, instance):
> super(RelatedManager, self).__init__()
E TypeError: __init__() takes exactly 2 arguments (1 given)
我知道它是因为构造函数参数,因为当我删除它(或给它一个默认值)时,所有测试都有效。
我怎样才能克服这个?这是实现此目标的正确方法吗?
技术资料:
- Django 1.9.5
- 测试框架py.test 2.9.1
谢谢
如您所见,发生该错误是因为每当您调用相关对象时,Django 都会实例化一个新的管理器;该实例化不会获得额外的参数。
与其以这种方式获取值,不如尝试将其设为模型的属性,然后通过 self.model
.
class MyManager(models.Manager):
def get_queryset(self):
# getting some value
kwargs = { self.model.manager_field_name: some_value }
class B:
manager_field_name = 'my_field_name'
objects = MyManager()
另一种选择是动态生成管理器class,例如:
def manager_factory(custom_field):
class MyManager(models.Manager):
my_field = custom_field
def get_queryset(self):
# getting some value
kwargs = {self.my_field: 'some-value'}
return super(MyManager, self).get_queryset().filter(**kwargs)
return MyManager()
class MyModel(models.Model):
objects = manager_factory('custom_field')
这样您就可以将管理器与模型分离 class。