使用GenericForeignKey()的非默认管理器

Mar*_*row 5 generics django content-type

我已经更改了一些GenericForeignKey()可以引用的对象的默认管理器,这些对象可能不再出现在该默认管理器中.

我有其他经理可以找到这些已删除的对象,但我认为没有办法告诉内容类型框架.这可能吗?

我正在使用一些涉及以下经理的模型实现"软删除":

from django.db import models

SDManager(models.Manager):

    def get_query_set(self):
        return super(SDManager, self).get_query_set().filter(is_deleted=False)

SDDeletedManager(models.Manager):

    def get_query_set(self):
        return super(SDDeletedManager, self).get_query_set().filter(is_deleted=True)
Run Code Online (Sandbox Code Playgroud)

这允许我执行以下操作:

SDModel(models.Model):
    # ...
    objects = SDManager() # Only non (soft) deleted objects
    all_objects = models.Manager() # The default manager
    deleted_objects = SDDeletedManager() # Only (soft) deleted objects
Run Code Online (Sandbox Code Playgroud)

当使用GenericForeignKey()模型中的字段来引用定义的对象(例如SDModel,它)时,它使用_default_managerobjects管理器求值的属性来获取引用.这意味着当对象被软删除时它会丢失引用.

这是我使用GenericForeignKey()字段的主要原因之一.我一直在研究的解决方案是实现内容类型框架的较小版本,以便我可以定义自己get_object()使用all_objects管理器来访问引用对象.

所以我的问题是:

是否可以使用现有内容类型框架的非默认管理器,以便找到软删除的对象,或者我是否必须从头开始重新实现所需的所有部分?

Spi*_*ike 2

我有和你完全相同的问题,在深入研究文档/源代码后,Django 似乎没有提供开箱即用的方法来执行此操作。我发现的最简单的方法是子类化GenericForeignKey然后重写该__get__方法。

麻烦的一行是它调用的地方:

rel_obj = ct.get_object_for_this_type(pk=getattr(instance, self.fk_field))
Run Code Online (Sandbox Code Playgroud)

所以这一行需要重写为:

rel_obj = ct.model_class().all_objects.get(pk=getattr(instance, self.fk_field))
Run Code Online (Sandbox Code Playgroud)

这有点黑客,但它确实有效,然后您就可以像平常一样使用 GenericForeignKey 的全部功能。