关于将模型中的自定义函数转换为自定义中的注解managers/querysets

About converting custom functions in models into annotations in custom managers/querysets

作为 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/ 就数据库调用而言,调用 function/property 的成本是多少

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

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)

虽然地址没问题,但好像找不到图片

如果有人有想法...

PS: For the image related functions, I mostly figured it out:

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'), Value(''), output_field=CharField()), ) I am however having an issue for the display of image_src through:

readonly_fields=['image'] def image(self, obj): return format_html(obj.image_src) it doesn't seem to find the image while the adress is ok.

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

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

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

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

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

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

然而,出于不同的目的,我更喜欢有一个可调用的(方法)而不是 属性

2/ 就数据库调用而言,调用 function/property 的成本是多少

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

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

因此,使用 @cached_property 装饰器而不是 @property 装饰器

来缓存这样 属性 的结果可能很有价值

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

from django.utils.functional import cached_property 

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

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

根据我目前的理解和实践,在 属性 和管理器

中复制相同的功能并不少见

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

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

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

已在之前的回答中回答