在Django中,如何使用管理器作为默认值而不是相关字段?

时间:2023-01-24 09:18:17

Let's say I've got FooManager() that I set as the default manager for a model Foo, i.e. by having it be the first manager that Django encounters in the model definition. Now, admin, dumpdata, and Django generally uses this manager by default, as desired.

假设我已经将FooManager()设置为模型Foo的默认管理器,即让它成为Django在模型定义中遇到的第一个管理器。现在,admin,dumpdata和Django默认情况下会根据需要使用此管理器。

However, I don't want related field managers to use FooManager(), i.e. if Foo has a foreign key to Bar, then the related manager bar_instance.foo_set should use the "plain" Foo manager (to use the term in Django docs), not FooManager.

但是,我不希望相关的字段管理器使用FooManager(),即如果Foo有一个Bar的外键,那么相关的管理器bar_instance.foo_set应该使用“普通”Foo管理器(在Django文档中使用该术语) ,而不是FooManager。

This doesn't seem possible, because the way to have FooManager NOT applied to related fields, is by setting its use_for_related_fields attribute to False. But all that does is get Django to use the the default manager (as opposed to the "plain" manager) for related fields.

这似乎不可能,因为将FooManager应用于相关字段的方法是将其use_for_related_fields属性设置为False。但所有这一切都是让Django使用相关字段的默认管理器(而不是“普通”管理器)。

And what's the default manager in this case? FooManager! Conundrum.

在这种情况下,默认的经理是什么? FooManager!难题。

Any way to make this work, i.e. use FooManager as default manager but not for related fields?

任何使这项工作的方法,即使用FooManager作为默认管理器,但不使用相关字段?

NOTE: I'm using Django 1.6. I don't see anything in the 1.7 docs to suggest default/related manager behavior has changed. Also note I do NOT want to have to explicitly set the related manager per the new 1.7 functionality here; I want the reverse related manager to use the plain manager by default, as I'm refactoring an existing project and would prefer not to change every reverse related manager reference.

注意:我正在使用Django 1.6。我在1.7文档中没有看到任何暗示默认/相关经理行为发生变化的内容。另请注意,我不想在此处根据新的1.7功能明确设置相关管理器;我希望反向相关的管理器默认使用普通管理器,因为我正在重构现有项目,并且不希望更改每个反向相关的管理器引用。

1 个解决方案

#1


1  

In this section the docs say the behavior is exactly what you want it to be.

在本节中,文档说行为正是您想要的行为。

The implementation also seems to do exactly what you want. 1.6 too.

实现似乎也完全符合您的要求。 1.6也是。

Update:

更新:

If you don't want to change every usage, then create subclass of ForeignKey, which uses subclass of ForeignRelatedObjectsDescriptor as a related_accessor_class with this method overwritten.

如果您不想更改每个用法,则创建ForeignKey的子类,它使用ForeignRelatedObjectsDescriptor的子类作为related_accessor_class并覆盖此方法。

Pseudo code:

伪代码:

class PlainManagerForeignRelatedObjectDescriptor(ForeignRelatedObjectDescriptor):

    @cached_property
    def related_manager_cls(self):
        return create_foreign_related_manager(
            models.Manager,
            self.rel,
        )

class PlainManagerForeignKey(ForeignKEy):
    related_accessor_class = PlainManagerForeignRelatedObjectDescriptor

#1


1  

In this section the docs say the behavior is exactly what you want it to be.

在本节中,文档说行为正是您想要的行为。

The implementation also seems to do exactly what you want. 1.6 too.

实现似乎也完全符合您的要求。 1.6也是。

Update:

更新:

If you don't want to change every usage, then create subclass of ForeignKey, which uses subclass of ForeignRelatedObjectsDescriptor as a related_accessor_class with this method overwritten.

如果您不想更改每个用法,则创建ForeignKey的子类,它使用ForeignRelatedObjectsDescriptor的子类作为related_accessor_class并覆盖此方法。

Pseudo code:

伪代码:

class PlainManagerForeignRelatedObjectDescriptor(ForeignRelatedObjectDescriptor):

    @cached_property
    def related_manager_cls(self):
        return create_foreign_related_manager(
            models.Manager,
            self.rel,
        )

class PlainManagerForeignKey(ForeignKEy):
    related_accessor_class = PlainManagerForeignRelatedObjectDescriptor