Django: создание таблицы оценки портфеля с двумя наборами запросов - PullRequest
0 голосов
/ 04 августа 2020

Я хочу построить таблицу позиций портфеля на основе этих моделей (models.py):

class Portfolio(models.Model):
    """
    Portfolio model, portfolio description
    """
    id = models.UUIDField(primary_key=True,default=uuid.uuid4,editable=False)
    code = models.CharField(max_length=100, blank=True)

class PortfolioPosition(models.Model):
    """
    PortfolioPosition Model, instruments hold in portfolio
    """
    portfolio = models.ForeignKey(Portfolio, on_delete=models.CASCADE, related_name='portfolio',null=True)
    private_debt_issue = models.OneToOneField(PrivateDebtIssue, on_delete=models.CASCADE)
    start_date = models.DateField(null=False, default=date.today)
    end_date = models.DateField(null=True, blank=True)
    quantity = models.DecimalField(max_digits=12, decimal_places=4, default=Decimal('1.0000'))

class PrivateDebtIssue(models.Model):
    """
    Model representing a Private Debt instrument. 
    """
    id = models.UUIDField(primary_key=True,default=uuid.uuid4,editable=False)
    name = models.CharField(max_length=250, blank=True)

class PrivateDebtIssueValuation(models.Model):
    """
    DataPoint value
    """
    private_debt_issue = models.ForeignKey(PrivateDebtIssue,on_delete=models.CASCADE,    related_name='private_debt_issue')

    date = models.DateField()
    fund_value = models.DecimalField(max_digits=12, decimal_places=2, default=Decimal('0.00'))

Возможно, это не лучший способ справиться с этим, но я хочу создать таблицу позиций портфеля со всеми открытыми позиции частного долга и последнее значение, основанное на дате ввода. Я написал этот код:

class PortfolioDetailView(DetailView):
    model = Portfolio
    context_object_name = 'portfolio'
    template_name = 'private_debts/portfolio_detail.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        # INPUT DATE BASED ON DATEPICKER
        # set default date value
        input_date = date.today()
        if self.request.method == 'GET':
            valuation_date = self.request.GET.get('valuation_date')
            if valuation_date is not None:
                input_date = datetime.strptime(valuation_date,'%m/%d/%Y')

        # based on Portfolio object get portfolio positions and related PrivateDebtIssue objects
        context['portfolio_position'] = PortfolioPosition.objects.all().select_related('portfolio','private_debt_issue').filter(
            Q(portfolio=self.object) 
            & Q(start_date__lte=input_date) 
            & (Q(end_date__isnull=True) | Q(end_date__gte=input_date))
        )
        context['position_value'] = queryset
        return context

Этот код работает нормально, но как мне получить значение PrivateDebtIssue для указанной c даты и поместить его в таблицу?

I хотите построить таблицу с портфелем PortfolioPosition .position, PrivateDebtIssue.Name и PrivateDebtIssueValuation.fund_value на основе даты оценки.

1 Ответ

0 голосов
/ 06 августа 2020

В конце концов, я сделал то, что не рекомендовалось в Django: прямой запрос с функцией execute. Вот так

class PortfolioDetailView(DetailView):
    model = Portfolio
    context_object_name = 'portfolio'
    template_name = 'private_debts/portfolio_detail.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        # set default date value
        input_date = date.today()
        input_date = date(2019,12,31)
        if self.request.method == 'GET':
            valuation_date = self.request.GET.get('valuation_date')
            if valuation_date is not None:
                input_date = datetime.strptime(valuation_date,'%m/%d/%Y')

        sql = """
            SELECT * \
            FROM private_debts_portfolioposition \
            INNER JOIN private_debts_privatedebtissue \
            ON (private_debts_portfolioposition.private_debt_issue_id = private_debts_privatedebtissue.id) \
            INNER JOIN private_debts_privatedebtissuevaluation \
            ON (private_debts_privatedebtissuevaluation.private_debt_issue_id = private_debts_privatedebtissue.id) \
            WHERE private_debts_portfolioposition.portfolio_id = '{}'::uuid \
            AND private_debts_privatedebtissuevaluation.date = '{}'
            """.format(self.object.id, input_date)

        portfolio_position = my_custom_sql(sql)
        context['portfolio_position_table'] = portfolio_position
        context['valuation_date'] = valuation_date
        return context

И я использовал пример, «предложенный» в docs Это две функции:

def dictfetchall(cursor):
    "Return all rows from a cursor as a dict"
    columns = [col[0] for col in cursor.description]
    return [
        dict(zip(columns, row))
        for row in cursor.fetchall()
    ]

def my_custom_sql(sql):
    with connection.cursor() as cursor:
        cursor.execute(sql)
        row = dictfetchall(cursor)
    return row

Я надеюсь, что кто-то может предложить лучший способ справиться с этим. Спасибо.

...