django的模型方法与管理器的自定义

目录

自定义管理器

自定义模型类方法

重写预定义模型方法

参考文献:


        粗浅来看,在django中为模型添加的自定义功能包括表级功能与行级功能,两者的区别即作用对象不同,对于行级功能其作用对象是面向模型的实例对象,也就是行数据。其中表级功能的实现通过自定义管理器的方法实现,行级功能的实现通过自定义模型类方法实现。

自定义管理器

        在django内对于数据库的操作是通过manager实现的。例如,task=Task.objects.get(id=task_id)中,objects是Task模型类的一个特别的类属性,其特别之处就在于其指向的是模型管理器,也就是manager,是django自动创建的。通过自定义模型管理器就可以定制数据库的更加简洁的操作方法。实现的方法有两种:一种是通过创建新的manager,另一种是在本身的manager上进行修改,重构返回的QuerySet。

  • 创建新的管理器
# 引用教程:https://www.w3cschool.cn/django4/django4-ptid3m0s.html
from django.db import models
from django.db.models.functions import Coalesce

# 创建PollManager类
class PollManager(models.Manager):
    # 创建分组统计方法
    def with_counts(self):
        return self.annotate(num_responses=Coalesce(models.Count("response"), 0))

class OpinionPoll(models.Model):
    question = models.CharField(max_length=200)
    # 将PollManager()赋值给OpinionPoll的objects类属性,相当于代替其本身的objects
    objects = PollManager()
# 自定义管理器的查询方法
OpinionPoll.objects.with_counts()
  • 修改管理器的QuerySet()
class TaskQuerySet(models.QuerySet):
    """自定义QuerySet类"""
    def with_label_summary(self):
        return self.prefetch_related(
            'label_set',
            'label_set__parent',
            'project__label_set',
            'project__label_set__parent',
        ).annotate(
            task_labels_count=models.Count('label',
                filter=models.Q(label__parent__isnull=True),
                distinct=True
            ),
            proj_labels_count=models.Count('project__label',
                filter=models.Q(project__label__parent__isnull=True),
                distinct=True
            ),)

class Task(models.Model):
    # 这里用了相对高级的写法,将TaskQuerySet作为默认的查询管理器
    objects = TaskQuerySet.as_manager()
# 自定义管理器的查询方法
Task.objects.with_label_summary()

自定义模型类方法

        举例说明自定义模型类方法,以下文get_labels(),get_dirname()为例:

# 创建方法
class Task(models.Model):
    objects = TaskQuerySet.as_manager()
    project = models.ForeignKey(Project, on_delete=models.CASCADE,
        null=True, blank=True, related_name="tasks",
        related_query_name="task")
    name = SafeCharField(max_length=256)
    mode = models.CharField(max_length=32)
    owner = models.ForeignKey(User, null=True, blank=True,
        on_delete=models.SET_NULL, related_name="owners")
    assignee = models.ForeignKey(User, null=True,  blank=True,
        on_delete=models.SET_NULL, related_name="assignees")
    bug_tracker = models.CharField(max_length=2000, blank=True, default="")
    created_date = models.DateTimeField(auto_now_add=True)
    updated_date = models.DateTimeField(auto_now=True)
    overlap = models.PositiveIntegerField(null=True)
    # Zero means that there are no limits (default)
    # Note that the files can be split into jobs in a custom way in this case
    segment_size = models.PositiveIntegerField(default=0)
    status = models.CharField(max_length=32, choices=StatusChoice.choices(), default=StatusChoice.ANNOTATION)
    data = models.ForeignKey(Data, on_delete=models.CASCADE, null=True, related_name="tasks")
    dimension = models.CharField(max_length=2, choices=DimensionType.choices(), default=DimensionType.DIM_2D)
    subset = models.CharField(max_length=64, blank=True, default="")
    organization = models.ForeignKey(Organization, null=True, default=None,
        blank=True, on_delete=models.SET_NULL, related_name="tasks")
    source_storage = models.ForeignKey('Storage', null=True, default=None,
        blank=True, on_delete=models.SET_NULL, related_name='+')
    target_storage = models.ForeignKey('Storage', null=True, default=None,
        blank=True, on_delete=models.SET_NULL, related_name='+')

    # Extend default permission model
    class Meta:
        default_permissions = ()

    def get_labels(self):
        project = self.project
        return project.get_labels() if project else self.label_set.filter(parent__isnull=True)

    def get_dirname(self):
        return os.path.join(settings.TASKS_ROOT, str(self.id))
# 使用方法
# 自定义模型类方法针对的是模型实例对象,因此先生成对象实例
task = Task.objects.get(name='')
# 实例的类方法
task.get_dirname()
task.get_label()

 

重写预定义模型方法

        暂时占位,后续补充

参考文献:

1、Django4 中文教程_w3cschool

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Felier.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值