首页 > 解决方案 > Django 从多个函数创建类

问题描述

我的 utils.py 文件中有几个函数,我的视图用于计算交易统计数据。下面我只添加了 3 个,但有 8 个,很快就会有更多。我目前设置它的方式有效,但效率非常低。您可以看到每个函数从头开始并调用设置类似变量的其他函数。

将其变成课程的正确方法是什么?

这甚至是正确的方法吗?


实用程序.py | 多种功能

def max_amount_function (pk):
    trade = get_object_or_404(Trade, pk=pk)
    entries_buy = Entry.objects.filter(trade=trade, entry_type="entry")
    max_amount_function = entries_buy.aggregate(max_amount_function=Sum('amount'))['max_amount_function']
    if max_amount_function is None:
        return 0
    else:
        return max_amount_function

def fees_function (pk):
    trade = get_object_or_404(Trade, pk=pk)
    entries = Entry.objects.filter(trade=trade)
    fees_function = entries.aggregate(fees_function=Sum('fee'))['fees_function']
    return fees_function

def entry_cpu_function (pk):
    if max_amount_function(pk) > 0:
        trade = get_object_or_404(Trade, pk=pk)
        entries_buy = Entry.objects.filter(trade=trade, entry_type="entry")
        entry_cpu_function = entries_buy.annotate(
            s=F('amount') * F('price')
        ).aggregate(
            entry_cpu_function=ExpressionWrapper(
                Sum(
                    Cast('s', output_field=models.FloatField())
                ) / Sum('amount'),
                output_field=models.FloatField()
            )
        )['entry_cpu_function']
        return entry_cpu_function
    else:
        return 0

实用程序.py | 一类

class TradeStats:
    trade = get_object_or_404(Trade)
    entries_buy = Entry.objects.filter(trade=trade, entry_type="entry")

    def __init__(self):
        pass

    def max_amount_functio(pk):
        pass

    def fees_function(pk):
        pass

    def entry_cpu_function(self):
        pass

编辑添加的 models.py,因为它可能与条目相关,因为它是不同的类。

模型.py

class Trade(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True)
    status = models.CharField(max_length=2, choices=STATUS_CHOICES, default='op')
    broker = models.ForeignKey(Broker, on_delete=models.CASCADE, blank=True, null=True)
    asset = models.ForeignKey(Asset, on_delete=models.CASCADE, null=True)
    ...

class Entry(models.Model):

    ENTRY = 'entry'
    EXIT = 'exit'
    ENTRY_TYPE_CHOICES = [
        (ENTRY, 'Entry'),
        (EXIT, 'Exit'),

    trade = models.ForeignKey(Trade, on_delete=models.CASCADE)
    amount = models.FloatField(null=True)
    price = models.FloatField(null=True, blank=True)
    entry_type = models.CharField(max_length=5, choices=ENTRY_TYPE_CHOICES, default=ENTRY)
    ...

标签: pythondjangofunctionclassmethods

解决方案


您可以将所有这些函数移动到模型或自定义 QuerySet 下。

如果你移动到模型,你可以做类似的事情。(代码可能不起作用,仅供参考)

# MODEL
class Trade(models.Model):

    # Model fields here

    def get_entries(self):
        # NB: assuming you didn't specify a related_name
        # in the `Entry.trade` ForeignKey field. Else,
        # replace `entry_set` with said related_name.
        return self.entry_set.filter(entry_type="entry")


    def max_amount_function(self):
        max_amount_res = self.get_entries().aggregate(max_amount_function=Sum('amount'))['max_amount_function']
        if max_amount_res is None:
            return 0
        else:
            return max_amount_res

    def fees_function(self):
        return self.get_entries().aggregate(fees_function=Sum('fee'))['fees_function']

    def entry_cpu_function(self, ):

        if self.max_amount_function() <= 0:
            return 0

        entry_cpu_function = self.get_entries().annotate(
            s=F('amount') * F('price')
        ).aggregate(
            entry_cpu_function=ExpressionWrapper(
                Sum(
                    Cast('s', output_field=models.FloatField())
                ) / Sum('amount'),
                output_field=models.FloatField()
            )
        )['entry_cpu_function']
        return entry_cpu_function

在 views.py 中,您可以像下面这样引用这个函数 -

trade = get_object_or_404(Trade, pk=pk)
trade.max_amount_function()
trade.fees_function()
trade.entry_cpu_function()

推荐阅读