繁体   English   中英

Django:按年分组日期

[英]Django: Group dates by Year

我试图从模型的创建字段创建像时间轴一样的东西,但我找不到一种干净的方法来做到这一点。 这个想法是向前端( DRF )返回一个包含日期的年份列表。 所以假设我有这个模型:

class ProductModel(models.Model):
  name = models.CharField(max_length=200)
  created = models.DateField(default=datetime.date.today, blank=True)

假设已经创建了 6 个产品(其中 3 个来自 2021 年,3 个来自 2022 年)。 所以我想返回这样的东西:

"timeline": {

    "2021": [
        ...,
        "2021-12-1",
        "2021-11-1",
        "2021-10-1",
    ],
    "2022": [
        ...,
        "2022-03-1",
        "2022-02-1",
        "2022-01-1",
    ],
}

这个想法只是返回创建产品的日期,没有别的。 但我现在不知道如何按年对日期进行分组。 我试过注释和值,但不是我需要的结果。 我知道在序列化器部分我必须使用 serializers.ListField() 才能将列表传递给它。

任何建议我都会洗耳恭听。 提前致谢:)

您在列表结构中使用了 key:pair,所以我假设它是错误的,您指的是字典。

对于该输出,一种可能的解决方案:

序列化器.py

class TimeLineSerializer(serializers.Serializer):

    timeline = serializers.SerializerMethodField()

    def get_timeline(self, obj):
        data = {}
        dates = obj.values('created__year').distinct()
        for date in dates:
            data[date['created__year']] = obj.filter(created__year=date['created__year']).values_list('created', flat=True)

        return data

意见.py:

class TimeLineListAPIView(APIView):
    def get(self, request):
        qs = ProductModel.objects.all()
        serializer = TimeLineSerializer(qs)
        return Response(serializer.data)

输出:

{
    "timeline": {
        "2021": [
            "2021-12-20",
            "2021-12-21",
            "2021-12-22"
        ],
        "2022": [
            "2022-12-20",
            "2022-12-21",
            "2022-12-23"
        ]
    }
}

当然,可能有一个我不知道的更清洁的解决方案。

我不知道这是否是最好的解决方案,但我创建了一个通用的 get_timeline 函数,它是这样的(感谢@Niko 的启发):

def get_timeline(model_queryset, lookup_field):
    '''
    get timeline function will return a dictionary of dates grouping by years.
    '''
    timeline = {}
    for item in model_queryset:
        if hasattr(item, lookup_field):
            date = getattr(item, lookup_field)
            filters = { f'{ lookup_field }__year': date.year }
            timeline[date.year] = model_queryset.filter(**filters).values_list(lookup_field, flat=True)
        else:
            raise ValidationError(f'Object "{ item }" does not have "{ lookup_field }" attribute')
    return timeline

在 views.py 中:

queryset =  ProductModel.objects.order_by('-created')
timeline = get_timeline(queryset, 'created')

和输出:

"timeline": {
    "2021": [
        "2021-12-1",
        "2021-11-1",
        "2021-10-1",
    ],
    "2022": [
        "2022-03-1",
        "2022-02-1",
        "2022-01-1",
    ],
},

此函数将在 views.py 文件中调用,将 ProductModel 对象作为“model_queryset”和“created”作为“lookup_field”传递。

希望这是一个干净的解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM