48

我有一个自定义管理器。我想将它用于相关对象。我在文档中找到 了 use_for_related_fields。但它不像我使用它的方式工作:

class RandomQueryset(models.query.QuerySet):

    def randomize(self):       
        count = self.count()
        random_index = random.randint(0, count - 1)
        return self.all()[random_index]


class RandomManager(models.Manager):

    use_for_related_fields = True

    def get_query_set(self):
        return RandomQueryset(self.model, using=self._db)

    def randomize(self):
        return self.get_query_set().randomize()

我将它用于一个模型:

>>> post = PostPages.default_manager.filter(image_gallery__isnull=False).distinct().randomize()

并尝试对 m2m 相关对象做同样的事情:

>>> post.image_gallery.randomize()

出现错误:

AttributeError: 'ManyRelatedManager' object has no attribute 'randomize'

是否可以像我一样使用自定义管理器?如果是这样,你如何使它工作?

编辑

我的模型:

class ShivaImage(models.Model, ImageResizing):
    image = models.ImageField(upload_to='img')
    slide_show = models.BooleanField() 
    title = models.CharField(max_length=100)
    text = models.TextField(max_length=400)
    ordering = models.IntegerField(blank=True, null=True)

    objects = RandomManager()


class PostPages(models.Model):
    image_gallery = models.ManyToManyField(ShivaImage, blank=True,
                                       related_name='gallery',)
    # all the other fields... 

    objects = RandomManager()
4

4 回答 4

43

为了主题的完整性,Django 1.7(最终)支持使用自定义反向管理器,因此您可以执行类似的操作(只需从 django 文档中复制):

from django.db import models

class Entry(models.Model):
    objects = models.Manager()  # Default Manager
    entries = EntryManager()    # Custom Manager

b = Blog.objects.get(id=1)
b.entry_set(manager='entries').all()
于 2014-09-24T07:04:59.447 回答
28

在管理器上设置use_for_related_fieldsTrue将使其在所有指向您将此管理器定义为默认管理器的模型的关系上可用。这记录在这里

class MyManager(models.Manager):
    use_for_related_fields = True
    # ...

我想你只在你的PostPages模型上启用了它,而不是在你的Gallery模型上(或者通过 引用的任何模型post_image_gallery)。如果你想在这个 realtion manager 上拥有额外的功能,你需要在use_for_related_fields = True你的Gallery模型中添加一个自定义的默认管理器!

于 2011-09-20T19:40:58.350 回答
19

在 django 2.0use_for_related_fields中已弃用https://docs.djangoproject.com/en/2.0/releases/1.10/#manager-use-for-related-fields-and-inheritance-changes

您应该使用base_manager_namehttps ://docs.djangoproject.com/en/2.0/ref/models/options/#django.db.models.Options.base_manager_name

更新的文档:https ://docs.djangoproject.com/en/2.0/topics/db/managers/#using-managers-for-related-object-access

class MyModel(models.Model):
    field1 = ...
    field2 = ...
    special_manager = MyManager()

    class Meta:
        base_manager_name = 'special_manager'
于 2018-01-06T06:23:28.917 回答
1

此外,在自定义管理器中,确保在实现要从相关管理器调用的自定义过滤器时通过 self.get_query_set() 代理方法访问查询集:

class EventManager(models.Manager):

    use_for_related_fields = True

    def visible_events(self):
        today = datetime.date.today()
        # don't do this !!! 
        # unsuitable for related managers as could retrieve extraneous objects
        # qs = super(EventManager, self).get_query_set()
        # Use queryset proxy method as follows, instead:
        qs = self.get_query_set()
        qs = qs.filter(visible_from__lte=today, visible_to__gte=today)
        return qs


class Event(models.Model):

    visible_from = models.DateField(_(u'visible from'), null=False, blank=False)
    visible_to = models.DateField(_(u'visible to'), null=False, blank=False)
    concepts = models.ManyToManyField(Concept, through='ConceptEventRegistration')

    objects = EventManager()

示例用法:

my_concept = Concept.objects.get(id=1)
# retrieve all events related to the object
my_concept.event_set.all()
# retrieve all visible events related to the object
my_concept.event_set.visible_events()
于 2015-01-18T07:01:30.897 回答