【问题标题】:Django QuerySet/Manager filter employees by age from birthdayDjango QuerySet/Manager 按年龄从生日开始过滤员工
【发布时间】:2018-03-27 12:56:06
【问题描述】:

我是初学者。我想列出年龄> 25 岁的员工名单并计算员工的平均年龄。目前,我们需要从生日开始计算年龄(我不知道它^^) .请帮我创建关于它的示例 QuerySet/Manager。

谢谢大家:))

我的模特:

class Employee(models.Model):
""""Employee model"""

    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    birthday = models.DateField(max_length=8)

注意:不会获取所有员工并从结果中过滤。 (results = Employee.objects.all()) 并且不使用原始 SQL。

【问题讨论】:

    标签: python django django-queryset


    【解决方案1】:

    如果您正在寻找自定义管理器,这是一个建议。

    import datetime
    from django.db import models
    
    # Create your models here.
    
    
    class EmployeeManager(models.Manager):
        def get_queryset(self):
            return super(EmployeeManager, self).get_queryset()
    
        def get_queryset_age_greater_25(self):
            # The `iterator()` method ensures only a few rows are fetched from the database at a time, saving memory.
            ids = [obj.id for obj in self.get_queryset().iterator() if obj.find_age() > 25]
            return self.get_queryset().filter(id__in=ids)
    
        def get_avg(self):
            sum_, count = sum(
                map(lambda obj: obj.find_age(), self.get_queryset_age_greater_25().iterator())), self.get_queryset_age_greater_25().count()
            return sum_/count
    
    
    class Employee(models.Model):
        first_name = models.CharField(max_length=30)
        last_name = models.CharField(max_length=30)
        birthday = models.DateField(max_length=8)
        objects = EmployeeManager()
    
        def find_age(self):
            return datetime.date.today().year - self.birthday.year
    

    然后使用

    Employee.objects.get_queryset_age_greater_25() # to get employee objects having age greater than 25)
    Employee.objects.get_avg() # to get avg age of employees having age greater than 25)
    

    【讨论】:

      【解决方案2】:
      from datetime import date
      from dateutil.relativedelta import relativedelta
      
      qs = Employee.objects.filter(birthdate__gt=date.today() - relativedelta(years=+25))
      

      预计25年+1天就够了。由于闰年,使用函数relativedelta,以在 2020 年 2 月 29 日不引发 ValueError 异常。

      【讨论】:

      • 谢谢,我已经应用它来获取年龄> 25岁的员工名单,计算员工的平均年龄怎么样?
      • 我不记得Query Expressions 的现代精确解决方案,但我确信它存在。一个经典的解决方案是最终将 Django 与 Python 评估结合起来。如果可能的话,也许Avg('birthdate') 或者计算到 1 月 1 日的平均值,没有年龄分数(Avg('birthdate__year') 或平均朱利安日期等。
      • Avg('birthdate__year') 在某些情况下不正确,我们应该知道使用 Avg 的确切年龄。感谢您的支持,我会进一步研究。
      • 您可以在此处发布您的答案,因为在 SO 上过时的最佳答案是 extra avg(UNIX_TIMESTAMP...)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-29
      • 1970-01-01
      • 2011-03-02
      • 1970-01-01
      • 1970-01-01
      • 2020-10-18
      • 1970-01-01
      相关资源
      最近更新 更多