• Django Manager Queryset


    Django Manager Queryset

    1.ORM objects

    我们使用 Django ORM进行数据库操作时,默认使用的Manager 对象是objects,每个Django模型默认拥有一个。

    类似如下情况:

    from django.db import models
    
    
    class Student(models.Model):
        name=models.CharField(max_length=128)
        ...
        objects=models.Manger()
        def get_student_by_name(self, name):
            return self.objects.get(name=name)
    

    2.自定义Manager

    class StudentManager(models.Manager):
        def  get_student_by_name(self, name):
            return self.filter(name=name)
        def get_student_by_id(self, id):
            return self.filter(id=id)
    
    class Student(models.Model):
        ...
        modify = StudentManager()
    

    ORM语句

    models.Student.modify.get_student_by_name(name)
    

    当我们只使用自定义Manager对象查询时,各个自定义方法是不能够链接的

    例如下面语法是错误的(此处的语句没有意义,仅用来说明问题)

    models.Student.modify.get_student_by_name(name=name).get_student_by_id(id=id)
    

    3.自定义queryset

    
    class StudentManager(models.Manager):
        def get_queryset(self):
            return super().get_queryset().filetr(...)
        
        def  get_student_by_name(self, name):
            return self.filter(name=name)
        
        def get_student_by_id(self, id):
            return self.filter(id=id)
    
    class Student(models.Model):
        ...
        modify = StudentManager()
    

    此时,我们使用如下语句查询会得到我们想要的QuerySet对象

    models.student.modify.all()
    

    对于三多提出的不能链接的问题此处就可以使用如下实例解决:

    class StudentQuerySet(models.QuerySet):
    	def get_queryset(self):
            super().get_queryset().filetr(...)
            
    	def  get_student_by_name(self, name):
            return self.filter(name=name)
        
        def get_student_by_id(self, id):
            return self.filter(id=id)
    
        
    class StudentManager(models.Manager):
        def get_queryset(self):
            return StudentQuerySet.get_queryset()
        
        def  get_student_by_name(self, name):
            return self.filter(name=name)
        
        def get_student_by_id(self, id):
            return self.filter(id=id)
    
    class Student(models.Model):
        ...
        modify = StudentManager()
    

    此时,如下语句是没有问题的:

    models.Student.modify.get_student_by_name(name=name).get_student_by_id(id=id)
    

    此时,我们会发现QuerySet 和Manager 有重复代码。

    使用as_manager解决

    如下,我们不直接实例化StudentManager类

    class Student(models.Model):
        ...
        modify = StudentQuerySet.as_manager()
    

    4.总结

    Django 官网指出,

    You can use a custom Manager in a particular model by extending the base Manager class and instantiating your custom Manager in your model.

    There are two reasons you might want to customize a Manager: to add extra Manager methods, and/or to modify the initial QuerySet the Manager returns.

    Adding extra Manager methods is the preferred way to add “table-level” functionality to your models. (For “row-level” functionality – i.e., functions that act on a single instance of a model object – use Model methods, not custom Manager methods.)

    A custom Manager method can return anything you want. It doesn’t have to return a QuerySet.

    关于使 models 肥胖(胖模型瘦控制器)还是抽离(业务逻辑应当在Django的什么位置)的讨论不是本文的目的。有情趣可以参考如下链接

    Where to put business logic in Django

    Django Best Practices — Refactoring Django Fat Models

    个人觉得业务逻辑存放于何处取决于你们团队最初的设计 DDD MVC 等。当然在不同设计模式下也有不同实现方式,有机会我们在共同学习分享!

  • 相关阅读:
    一个数组中去除某一部分数组
    关于函数的同步异步
    多维数组转一维数组
    关于Promise的详细总结
    关于ES6(ES2015)的知识点详细总结
    vue实现一个会员卡的组件(可以动态传入图片(分出的一个组件)、背景、文字、卡号等)
    GitHub上常用命令(工作中几乎每天用到的命令)
    gitHub上如何设置或者取消电子邮箱提醒
    React评论展示案例(包含知识点:state、props、ref、React声明周期、localStorage本地存储等)
    感想2-对于组件化的一些思考
  • 原文地址:https://www.cnblogs.com/9527mwz/p/13588723.html
Copyright © 2020-2023  润新知