是否可以将F()表达式传递给数据库 annotate 调用内的dateutil等 relativedelta 之类的函数。
在以下情况下, InterestLoan.objects.active_loans(start_date ='2018-01-01',end_date ='2019-01-01')打算返回一个查询集在给定期间内的有效贷款余额。需要使用开始日期 + 条款对结束日期进行注释。
相反,我收到TypeError:一元+的错误操作数类型:'F'
class InterestLoanSet(models.QuerySet):
def add_end_date(self):
return self.annotate(loan_end_date=ExpressionWrapper(F('start_date') + relativedelta(months=+F('term'), output_field=DateField())))
def active_loans(self, start_date, end_date):
return self.exclude(start_date__gt=end_date).add_end_date().exclude(loan_end_date__lt=start_date)
class InterestLoan(AbstractTransaction):
objects = InterestLoanSet.as_manager()
interest_nominal_code = models.ForeignKey(NominalCode, null=False, on_delete=models.PROTECT)
balance_nominal_code = models.ForeignKey(NominalCode, null=False, on_delete=models.PROTECT, related_name='loans')
principal = models.DecimalField(max_digits=10, decimal_places=2)
term = models.PositiveIntegerField()
interest_rate = models.DecimalField(max_digits=4, decimal_places=4)
答案 0 :(得分:0)
这是在丹尼尔·罗斯曼(Daniel Roseman)评论后发现的一种解决方案,该表达式需要在数据库中处理。
class InterestLoanSet(models.QuerySet):
def add_end_date(self):
return self.annotate(loan_end_year=ExpressionWrapper(ExtractYear('start_date') + F('term'), output_field=IntegerField()))
def active_loans(self, range_start_date, range_end_date):
return self.exclude(start_date__gt=range_end_date).add_end_date().exclude(loan_end_year__lt=range_start_date.year, start_date__month__lt=start_date.month)
class InterestLoan(AbstractTransaction):
objects = InterestLoanSet.as_manager()
interest_nominal_code = models.ForeignKey(NominalCode, null=False, on_delete=models.PROTECT)
balance_nominal_code = models.ForeignKey(NominalCode, null=False, on_delete=models.PROTECT, related_name='loans')
principal = models.DecimalField(max_digits=10, decimal_places=2)
term = models.PositiveIntegerField()
interest_rate = models.DecimalField(max_digits=4, decimal_places=4)
此过滤器每年过滤一次,但需要做得更复杂才能在月或日过滤。
对Kyle Hansan的article表示敬意