【补充】根据年月对文章进行分组

发布时间 2023-07-21 15:52:32作者: Chimengmeng

【补充】根据年月对文章进行分组

【一】官方文档的参考写法

Django官网提供的 orm 语法

# django官网提供的一个orm语法
    from django.db.models.functions import TruncMonth
-官方提供
            from django.db.models.functions import TruncMonth
            Sales.objects
            .annotate(month=TruncMonth('timestamp'))  # Truncate to month and add to select list
            .values('month')  # Group By month
            .annotate(c=Count('id'))  # Select the count of the grouping
            .values('month', 'c')  # (might be redundant, haven't tested) select month and countSales就是指models里面的模型类
  1. from django.db.models.functions import TruncMonth:导入TruncMonth函数,该函数用于将日期时间字段截断到月份,并将其添加到选择列表中。

  2. Sales.objectsSales是一个模型类,通过使用objects属性可以获取该模型类对应的查询集对象,可以对其进行查询和操作。

  3. annotate(month=TruncMonth('timestamp')):使用annotate方法扩展查询集,在结果中添加一个名为month的字段,并使用TruncMonth函数对timestamp字段进行截断。

  4. .values('month'):将结果按照month字段进行分组。

  5. .annotate(c=Count('id')):对分组后的结果再次使用annotate方法,在结果中添加一个名为c的字段,该字段表示每个分组中id字段的计数。

  6. .values('month', 'c'):指定返回结果中的字段,包括monthc字段。

【二】简单的示例

# 按照年月统计所有的文章
    date_list = models.Article.objects.filter(blog=blog).annotate(month=TruncMonth('create_time')).values("month").annotate(count_num=Count("pk")).values_list('month','count_num')

# 先filter(blog=blog)查找到当前用户的所有文章
# annotate(month=TruncMonth('create_time')) 以创建时间的月分组
# 第二个annotate前的values("month")是分组条件

【三】我的项目中的演示

year, month = param.split('-')  # 2023-06  > [2023,06]
article_list = article_list.filter(create_time__year=year, create_time__month=month)

【四】扩展

【Trunc】

  • Trunc:
    • 这是一个用于日期时间字段截断的函数类。
    • 它可以用于按照指定的单位(如年、月、周等)来截断日期时间字段。
    • Trunc 函数可以根据具体需求选择不同的截断单位
      • 例如 TruncYear(按年截断)
      • TruncMonth(按月截断)
      • TruncDay(按天截断)等。

【Extract】

  • Extract:
    • 这个函数类用于从日期时间字段中提取指定部分(如年、月、日等)。
    • 可以使用具体的 Extract 函数
      • ExtractYear(提取年份)
      • ExtractMonth(提取月份)
      • ExtractDay(提取天数)等。

【1】TruncMonth

  • 当使用TruncMonth函数时
    • 它可以用于按照月份截断日期时间字段。
    • 下面是一个使用TruncMonth函数的示例:
  • 假设我们有一个模型类Transaction
    • 其中包含一个date字段,表示交易发生的日期。
  • 我们可以使用TruncMonth函数来按月份截断日期
    • 并计算每个月的交易总额。
from django.db.models import Sum
from django.db.models.functions import TruncMonth
from myapp.models import Transaction

# 查询每个月的交易总额
monthly_totals = Transaction.objects.annotate(
    month=TruncMonth('date')
).values('month').annotate(
    total_amount=Sum('amount')
).order_by('month')

for entry in monthly_totals:
    month = entry['month']
    total_amount = entry['total_amount']
    print(f"{month.strftime('%Y-%m')}: {total_amount}")
  • 在上面的示例中,首先使用annotate方法和TruncMonth('date')来创建一个新的字段month
    • 该字段对应于每个交易的月份。
  • 然后使用valuesannotate来分组并计算每个月的交易总额。
  • 最后使用order_by对结果进行排序。

【2】TruncYear

  • TruncYear是Django ORM中的一个函数

    • 用于按照年份截断日期时间字段。
    • 下面是对TruncYear函数的详细解释和使用案例:
  • TruncYear函数可以将日期时间字段按照年份进行截断

    • 得到该年的开始日期。
  • 这个函数可以用于统计某一年的数据

    • 或者按年份进行分组和聚合操作。
  • 下面是一个使用TruncYear函数的示例:

  • 假设我们有一个模型类Transaction

    • 其中包含一个名为transaction_date的日期字段
    • 表示交易发生的日期。
    • 我们希望按年份统计每年的交易总额。
from django.db.models import Sum
from django.db.models.functions import TruncYear
from myapp.models import Transaction

# 查询每年的交易总额
yearly_totals = Transaction.objects.annotate(
    year=TruncYear('transaction_date')
).values('year').annotate(
    total_amount=Sum('amount')
).order_by('year')

for entry in yearly_totals:
    year = entry['year']
    total_amount = entry['total_amount']
    print(f"{year.year}: {total_amount}")
  • 在上面的示例中,我们首先使用annotate方法和TruncYear('transaction_date')函数创建了一个新字段year
    • 该字段对应于每个交易的年份。
  • 然后使用valuesannotate对年份进行分组并计算每年的交易总额。
  • 最后使用order_by对结果按照年份进行排序。
  • 请注意,由于TruncYear函数将日期字段按照年份截断,所以在使用时需要根据自己的模型和字段名称进行相应的调整,以确保代码的正确执行。

【3】TruncDay

  • TruncDay是Django ORM中的一个函数

    • 用于按照天数截断日期时间字段。
  • 下面是对TruncDay函数的详细解释和使用案例:

    • TruncDay函数可以将日期时间字段按照天数进行截断
    • 得到该天的开始时间。
    • 这个函数可以用于按天统计数据、按天进行分组和聚合操作
    • 或者筛选某个特定的日期范围内的数据。
  • 下面是一个使用TruncDay函数的示例:

    • 假设我们有一个模型类Sales,其中包含一个名为sale_date的日期字段
    • 表示销售发生的日期。
    • 我们希望按天统计每天的销售总额。
from django.db.models import Sum
from django.db.models.functions import TruncDay
from myapp.models import Sales

# 查询每天的销售总额
daily_totals = Sales.objects.annotate(
    day=TruncDay('sale_date')
).values('day').annotate(
    total_amount=Sum('amount')
).order_by('day')

for entry in daily_totals:
    day = entry['day']
    total_amount = entry['total_amount']
    print(f"{day.date()}: {total_amount}")
  • 在上面的示例中
    • 我们首先使用annotate方法和TruncDay('sale_date')函数创建了一个新字段day
    • 该字段对应于每个销售的日期。
    • 然后使用valuesannotate对日期进行分组并计算每天的销售总额。
    • 最后使用order_by对结果按照日期进行排序。
  • 请注意
    • 由于TruncDay函数将日期字段按照天数截断
    • 所以在使用时需要根据自己的模型和字段名称进行相应的调整,以确保代码的正确执行。