关于将模型中的自定义函数转换为自定义管理器/查询集中的注释

时间:2019-12-14 09:07:29

标签: python django django-queryset django-annotate

作为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)

地址正确时似乎找不到图像。

如果有人有主意...

2 个答案:

答案 0 :(得分:0)

  

PS:对于图像相关的功能,我主要是弄清楚了:

     

self.annotate(image_url = Concat(Value(join(settings.SVG_DIR,'')),   F('全名'),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):       返回format_html(obj.image_src),但在地址正常时似乎找不到图像。

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

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

答案 1 :(得分:0)

现在有了 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 函数转换为注释

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