重写Django的RelatedManager方法

12 投票
3 回答
4616 浏览
提问于 2025-04-16 09:58

Django中的ForeignRelatedObjectsDescriptor.create_manager(...)这个函数可以动态地创建RelatedManager类,并且会初始化这个新创建的类的实例。

如果我想要修改RelatedManager.add(...)这个方法,我该怎么做呢?

RelatedManager类是在这个文件中创建的:django/db/models/fields/related.py

我想使用自定义的RelatedManager的一个例子是...

class Record(Model):
    string = CharField()
class Managed(Model):
    record = ForeignKey('Record')
    boolean = BooleanField()
def view_function(...):
    record = Record(string='Example')
    record.save()
    record.managed_set.add(Managed(boolean=True)) # How to override add()?

任何建议都非常感谢。

3 个回答

0

RelatedManager.add() 这个方法会调用 RelatedManager._add_items(),而这个方法又会调用 Manager.bulk_create()

所以,如果你对 Manager.bulk_create() 进行扩展,可能就能实现你想要的功能。

0

我觉得我遇到了同样的问题。

我有一个自定义的管理器,它重写了 self._dbget_query_set(),这样可以把请求导向不同的数据库。

我动态创建了一个 模型 类,并把它的 _default_manager 设置为我的自定义管理器。

这样在类本身上是有效的,但在关联字段(比如外键或多对多关系)上就不行,尽管我设置了 use_for_related_fields = True

对于关联字段,添加 db_manager(dbname)(比如 record.managed_set.db_manager(dbname))可以解决 all() 方法的问题,但对 add() 方法就不管用了。

想要理解我说的内容,可以看看这个 Django 的问题单:http://code.djangoproject.com/ticket/13358

我觉得对 all() 有效,但对 add() 就不行。

4

我不太明白你为什么需要重写这个,默认的查询集已经能满足你的需求了。

不过为了回答你的问题,你可以在模型上定义一个自定义的管理器,并设置 use_for_related_fields=True,这样它就会被用作自动管理器。你可以查看这部分的文档,了解更多关于 自动管理器类型的控制

撰写回答