如何使用自定义管理器与相关对象?

I15*_*159 41 django django-orm django-managers

我有一个自定义经理.我想将它用于相关对象.我在docs中找到了 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()
Run Code Online (Sandbox Code Playgroud)

我用它作为一个型号:

>>> post = PostPages.default_manager.filter(image_gallery__isnull=False).distinct().randomize()
Run Code Online (Sandbox Code Playgroud)

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

>>> post.image_gallery.randomize()
Run Code Online (Sandbox Code Playgroud)

出了错误:

AttributeError: 'ManyRelatedManager' object has no attribute 'randomize'
Run Code Online (Sandbox Code Playgroud)

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

编辑

我的模特:

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()
Run Code Online (Sandbox Code Playgroud)

Ser*_*eim 30

为了完整的主题,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()


Ber*_*ant 26

设置use_for_related_fieldsTrue对经理将使其可在这一点,所有的关系,以在其上定义了这个经理为默认管理模型.这在此处记录

class MyManager(models.Manager):
    use_for_related_fields = True
    # ...
Run Code Online (Sandbox Code Playgroud)

我想你只在你的PostPages模型上启用它,而不是你的Gallery模型(或者通过引用的模型被调用post_image_gallery).如果您想在此Realtion Manager上拥有其他功能,则需要use_for_related_fields = True为您的Gallery模型添加自定义默认管理器!

  • 警告,从Django 1.10开始,不推荐使用此功能,而是在模型上设置Meta.base_manager_name.请参阅https://docs.djangoproject.com/en/1.10/releases/1.10/#manager-use-for-related-fields-and-inheritance-changes中的发行说明. (26认同)
  • 其他警告:文档还说在查询相关对象时不使用管理器.https://docs.djangoproject.com/en/1.11/topics/db/managers/#django.db.models.Model._base_manager.这可以防止使用该功能隐含地过滤掉相关对象. (5认同)
  • 定义的 _first_ 管理器成为默认管理器,无论它是否称为“对象”... (2认同)

Sar*_*iev 10

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

您应该使用base_manager_name:https://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'
Run Code Online (Sandbox Code Playgroud)

  • `base_manager_name`希望有问题的管理器的名称是一个字符串,而不是实例.见[this](https://github.com/django/django/blob/8dc675d90f14a84ef95f16c7cc8100d9a04459b3/tests/custom_managers/models.py#L158). (3认同)
  • 对我来说,在覆盖模型中的默认“objects”属性时甚至需要设置“base_manager_name”(之前,我认为只有当管理器名称与默认“objects”不同时才需要设置“base_manager_name”)! (2认同)