子类a Django ManyRelatedManager a.k.a.ManyToManyField

2024-10-03 23:30:10 发布

您现在位置:Python中文网/ 问答频道 /正文

有没有办法将Django manyratedmanager a.k.a.ManyToManyField子类化?在

目标是在调用ManyRelatedManager时使用deleted=None来预过滤所有相关模型。如果deleted=None,则它是一个有效的Model。在

到目前为止,这是代码,但似乎不起作用。在

class ExcludeDeletedManyToManyField(models.ManyToManyField):

    def get_queryset(self):
        qs = super(ExcludeDeletedManyToManyField, self).get_queryset()
        return qs.filter(deleted__isnull=True)


class SelfRefrencingModel(models.Model):

    children = ExcludeDeletedManyToManyField('self', blank=True,
        symmetrical=False, related_name='parents')

Tags: djangoselfnonetruegetmodelmodelsclass
3条回答

您可以创建SelfRefrencingModelproxy model,并覆盖默认的manager。然后在ManyToManyField中使用此代理模型。在

子类化ManyToManyField对您没有帮助,因为对于结果查询集,ManyRelatedManger负责。在

代理模型方法:

from django.db import models

class A(models.Model):
    children = models.ManyToManyField('AProxy')
    name = models.TextField()
    deleted = models.NullBooleanField(null=True)


class FilterDeletedManager(models.Manager):
    def get_queryset(self):
        qs = super(FilterDeletedManager, self).get_query_set()
        return qs.filter(deleted__isnull=True)


class AProxy(A):
    objects = FilterDeletedManager()
    class Meta:
        proxy = True

这种方法需要注意的是,django现在需要AProxy个实例作为children字段。在

所以,也许更好的可读性和可维护性方法是在__init__中添加另一个属性。在

^{pr2}$

如果您打算在Django-Admin或ModelForm中使用它,则不需要将ManyToManyField子类化。参见django documentation

class SelfRefrencingModel(models.Model):

    children = models.ManyToManyField('self', blank=True, symmetrical=False, 
        related_name='parents', limit_choices_to={'deleted': False}))

注意:如果deletedBooleanField,则必须是True或{}。它不能是None/NULL。在

beezz的使用代理模型的想法也是一个好主意。在

我有时会定制默认管理器 ^{pr2}$

默认情况下,deleted对象将被隐藏,但如果在查询集中需要它们,可以使用_objects。在

这是我的解决方案。@beezz,使用代理模型来完成此操作可能是正确的,但在此模式中,我以前从未使用过代理模型,因此我解决此问题的方法如下:

class SelfRefrencingQuerySet(models.query.QuerySet):
    pass

class SelfRefrencingManager(BaseManager):

    def get_queryset(self):
        return SelfRefrencingQuerySet(self.model, self._db).filter(
            deleted__isnull=True)

class SelfRefrencingBaseModel(models.Model):

    children = models.ManyToManyField('self', blank=True, symmetrical=False,
        related_name='parents')

    # Manager
    objects = SelfRefrencingManager()
    objects_all = models.Manager()     # So you still have acccess to the
                                       # default Manager

相关问题 更多 >