【问题标题】:About converting custom functions in models into annotations in custom managers/querysets关于将模型中的自定义函数转换为自定义管理器/查询集中的注释
【发布时间】:2020-04-07 13:34:32
【问题描述】:

作为 Django 新手,我开始有点关心我的 Web 应用程序的性能。

我正在尝试将最初在我的模型中的许多自定义函数/属性转换为自定义管理器中的查询集。

在我的模型中我有:

class Shape(models.Model): 
    @property
    def nb_color(self):
        return 1 if self.colors=='' else int(1+sum(self.colors.upper().count(x) for x in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'))

    def __str__(self):
        return  self.name + "-" + self.constraints

    @property
    def image_url(self):
        return format_html(f'{settings.SVG_DIR}/{self}.svg')

    @property
    def image_src(self):
        return format_html('<img src="{url}"|urlencode />'.format(url = self.image_url))

    def image_display(self):
        return format_html(f'<a href="/static/SVG_shapes/{self}">{self.image_src}"</a>')

但有几点我不清楚:

1/ 在 django 模型中使用适当的装饰器声明是否有任何优点或缺点?

2/ 就数据库调用而言,调用函数/属性的成本是多少

因此,使用自定义管理器/查询集并定义注释以在该级别模拟我的功能是否有附加价值?

3/ 你建议我如何将图像和 nb_color 函数转换为注释

提前致谢

PS:对于图片相关的功能,我主要是想通了:

self.annotate(image_url = Concat(Value(join(settings.SVG_DIR,'')), F('fullname'), Value('.svg'), output_field=CharField()),
                        image_src = Concat(Value('<img src="'), F('image_url'), Value('"|urlencode />'), output_field=CharField()),
                        image_display = Concat(Value('<a href="'+ settings.SVG_DIR+'/'), F('fullname'), Value('.svg">'),F('image_src'), Value('</a>'), output_field=CharField()),
                        )

然而,我在显示 image_src 时遇到了问题 通过:

readonly_fields=['image']
def image(self, obj):
    return format_html(obj.image_src)

地址没问题的时候好像没找到图片。

如果有人有想法...

【问题讨论】:

    标签: python django django-queryset django-annotate


    【解决方案1】:

    PS:对于图片相关的功能,我主要是想通了:

    self.annotate(image_url = Concat(Value(join(settings.SVG_DIR,'')), F('fullname'), Value('.svg'), output_field=CharField()), image_src = Concat(Value(''), output_field=CharField()), image_display = Concat(Value(''),F('image_src'), 值(''), output_field=CharField()), ) 但是,我在通过以下方式显示 image_src 时遇到问题:

    readonly_fields=['image'] def image(self, obj): return format_html(obj.image_src) 在地址正常的情况下似乎找不到图像。

    我为我的图像问题想出来了:我应该简单地使用相对路径并让 Django 管理:

    self.annotate(image_url = Concat(Value('/static/SVG_shapes/'), F('fullname'), Value('.svg'), output_field=CharField()),)
    

    【讨论】:

      【解决方案2】:

      现在有了 1.5 年的经验,我将尝试为下一个可能有相同问题的人回答我的新手问题。

      1/ 在 django 模型中使用适当的装饰器声明是否有任何优点或缺点?

      到目前为止我没有看到任何缺点。

      它允许将数据作为模型的属性检索(my_shape.image_url),而不必调用相应的方法(my_shape.image_url()

      但是,出于不同的目的,我更喜欢使用可调用(方法)而不是属性

      2/ 就数据库调用而言,调用函数/属性的成本是多少

      如果需要作为输入的数据已经可用,或者它们本身就是实例对象的属性(不需要从实例对象外部输入的字段/属性/方法),则无需额外调用数据库

      但是,如果需要外部数据,将为它们中的每一个生成一个数据库调用。

      因此,使用 @cached_property 装饰器而不是 @property 装饰器来缓存此类属性的结果可能很有价值

      使用缓存属性唯一需要的是以下导入:

      from django.utils.functional import cached_property 
      

      在第一次调用后,缓存的属性将在对象实例的整个生命周期内保持可用,无需额外费用, 并且它的内容可以像任何其他属性/变量一样被操纵:

      因此,使用自定义管理器/查询集并定义注释以在该级别模拟我的功能是否有附加价值?

      根据我目前的理解和实践,在物业和经理中复制相同的功能并不少见

      原因是当我们只对一个特定的对象实例感兴趣时,属性很容易获得, 而当您有兴趣比较/检索一系列对象的给定属性时,为整个查询集计算和注释此属性会更有效,例如通过使用模型管理器

      我的赠品是: 对于给定的模型, (1) 尝试将与单个对象实例相关的所有业务逻辑放入模型方法/属性中 (2) 以及所有涉及一系列对象的业务逻辑到模型管理器中

      3/您建议我如何将图像和 nb_color 函数转换为注释

      已经在之前的回答中回答过

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-05-26
        • 1970-01-01
        • 2018-03-23
        • 2022-01-21
        • 2017-07-20
        • 1970-01-01
        • 2016-07-28
        • 1970-01-01
        相关资源
        最近更新 更多