VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > Python基础教程 >
  • 建立一个更高级别的查询 API:正确使用Django ORM 的方式(3)

这个接口将以这样的方式展现:

1
2
>>> Todo.incomplete.all()
>>> Todo.high_priority.all()

这个方法有几个问题。

第一,这种实现方式比较啰嗦。你要为每一个query自定义功能定义一个class。

第二,这将会弄乱你的命名空间。Django开发者吧Model.objects看做表的入口。这样做会破坏命名规则。

第三,不可链接的。这样做不能将managers组合在一起,获得不完整,高优先级的todos,还是回到低等级的ORM代码:Todo.incomplete.filter(priority=1) 或Todo.high_priority.filter(is_done=False)

综上,使用多managers的方法,不是最优选择。

方法2: Manager 方法

现在,我们试下其他Django允许的方法:在单个自定义Manager中的多个方法

1
2
3
4
5
6
7
8
9
10
11
12
class TodoManager(models.Manager):
    def incomplete(self):
        return self.filter(is_done=False)
 
    def high_priority(self):
        return self.filter(priority=1)
 
class Todo(models.Model):
    content= models.CharField(max_length=100)
    # other fields go here..
 
    objects= TodoManager()

我们的API 现在看起来是这样:

1
2
>>> Todo.objects.incomplete()
>>> Todo.objects.high_priority()

这个方法显然更好。它没有太多累赘(只有一个Manager类)并且这种查询方法很好地在对象后预留命名空间。(译注:可以很形象、方便地添加更多的方法)

不过这还不够全面。 Todo.objects.incomplete() 返回一个普通查询,但我们无法使用 Todo.objects.incomplete().high_priority() 。我们卡在 Todo.objects.incomplete().filter(is_done=False),没有使用。

方法3:自定义QuerySet

现在我们已进入Django尚未开放的领域,Django文档中找不到这些内容。。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class TodoQuerySet(models.query.QuerySet):
    def incomplete(self):
        return self.filter(is_done=False)
 
    def high_priority(self):
        return self.filter(priority=1)
 
class TodoManager(models.Manager):
    def get_query_set(self):
        return TodoQuerySet(self.model, using=self._db)
 
class Todo(models.Model):
    content= models.CharField(max_length=100)
    # other fields go here..
 
    objects= TodoManager()

相关教程