将方法添加到RelatedManager

时间:2017-05-14 10:08:34

标签: python django django-models

我使用以下属性从模板访问有序查询集:

class Question(models.Model):
    @property
    def descending_choice_set(self):
        """
        Order choice_set by votes descending.
        """
        return self.choice_set.order_by('-votes')

但我希望question.choice_set.order_by_votes代替question.descending_choice_set来访问它。对于此行为,必须覆盖RelatedManager。怎么能实现呢?

2 个答案:

答案 0 :(得分:0)

您可以创建自定义管理器并将order_by_votes等所有方法放入其中。这是一个例子:

from django.db import models

class ChoiceManager(models.Manager):
  def order_by_votes(self):
    return self.order_by('-vote_number')

# Create your models here.
class Choice(models.Model):
  name = models.CharField(max_length=255)
  vote_number = models.IntegerField()

  # register your manager. You literally can put any variable name here. 
  # Just do not forget to access manager through it later :)
  objects = ChoiceManager()

  def __str__(self):
    return self.name

用法:

In [1]: from app import models
In [2]: c = models.Choice.objects.create(name='first', vote_number=1)
In [3]: c = models.Choice.objects.create(name='second', vote_number=2)
In [4]: models.Choice.objects.order_by_votes()
Out[5]: <QuerySet [<Choice: second>, <Choice: first>]>

答案 1 :(得分:0)

正如塔拉斯所说,你可以写一个自定义经理。但是编写自定义管理器只允许为模型本身调用该方法。 要覆盖相关的管理器方法,您需要使用设置use_for_related_fields

在管理器上将use_for_related_fields设置为True将使其可用于指向您将此管理器定义为默认管理器的模型的所有关系。记录在案here

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

    def order_by_votes(self):
        return self.order_by('-vote_number')

为模型编写自定义管理器,并将上述设置设置为True。我建议为Question和Choice模型编写管理器以获得更好的功能并添加设置。