【问题标题】:Django: Filter by calculated fieldDjango:按计算字段过滤
【发布时间】:2016-11-07 19:34:05
【问题描述】:

在我的 Django 项目中,我需要计算旅行的日期范围,以查看旅行当前是否在途中。

class TourTemplate(models.Model):
    length = models.IntegerField()
    description = models.TextField(max_length=1000)
...

class Trip(models.Model):
    tourtemplate = models.ForeignKey(TourTemplate)
    start = models.DateField()
...

我将此添加到我的 Trip 模型中:

def end(self):
    length = self.tourtemplate.length
    start = self.start
    a = start + timedelta(days=length)
    return a

它在 shell 中工作并返回单个对象的结束日期。但是如何过滤我的查询集,以便只获取开始日期和计算结束日期之间的对象?

【问题讨论】:

  • 您是否尝试过任何方法来“过滤我的查询集,以便我只获取开始日期和计算结束日期之间的对象?”你应该展示那个部分,即艺术人员可以提供更多帮助
  • 我尝试注释结束日期:Trip.objects.all().annotate(end=Trip.end()) 这给了我“end() 缺少 1 个必需的位置参数:'self'”
  • 您想使用对象的开始日期和计算的结束日期来查找两个给定日期内的对象吗?
  • 看看this。应该有帮助

标签: python django django-models django-views


【解决方案1】:
# First, define a manager subclass
class TripManager(models.Manager):
    def get_queryset(self):
        length= self.tourtemplate.length
        start= self.start
        end=start+ timedelta(days=length)
        return super(TripManager, self).get_queryset().filter(date__range=[start, end])

class Trip(models.Model):

    objects = models.Manager() # The default manager.
    current_trip = TripManager() # New manager

现在,您可以致电:

Trip.current_trip.all()

两个要点:

  1. 您在模型中定义的函数只能在该模型的实例(函数所在的位置)上调用。
  2. 由于第 1 点,您的情况需要自定义模型管理器。从link 了解它们。您的默认管理器由 Model.objects.all() 调用,如果您想更改或修改默认管理器返回的查询集,定义自定义管理器会很方便。

尝试上述解决方案。希望对你有帮助:)

【讨论】:

  • 非常感谢 Shubhanshu 的解决方案和解释。这看起来和我要找的完全一样 :) 我回家后会试一试并报告。
  • 不幸地调用Trip.current_trip.all()返回AttributeError: 'TripManager' object has no attribute 'tourtemplate'。在我见过的所有示例中,模型管理器仅用于过滤。我们真的可以按照您描述的方式使用它吗?
  • 您为什么不尝试在自定义管理器中的 get_queryset 方法上方插入 use_for_related_fields = True 。看看这个链接:stackoverflow.com/questions/7489635/… 和这个链接:docs.djangoproject.com/en/dev/topics/db/managers/#manager-types
  • date__range=[start, end] 来自哪里??
【解决方案2】:

无法弄清楚如何将我的计算值插入到查询集中。我的解决方案是为结束日期添加另一个日期字段 (editable=False),并在创建新行程时计算并保存结束日期:

# Calculate end date on save
def save(self, *args, **kwargs):
    self.end = self.start+ timedelta(days=self.tourtemplate.length)
    super(Trip, self).save(*args, **kwargs)

【讨论】:

    猜你喜欢
    • 2016-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-30
    • 1970-01-01
    • 1970-01-01
    • 2022-08-14
    相关资源
    最近更新 更多