背景:
嗨,各位。我有一个模型Transplant
,它描述了在给定时间移植的植物种类。以下是我的模型,归结为一个简单的形式:
class Species(models.Model):
name = models.TextField()
class Transplant(models.Model):
datetime = models.DateTimeField()
species = models.ManyToManyField(Species, related_query_name='transplants')
问题:
我想提供API的结果,这些结果由我的DateTimeField
的日期组件分页,并显示日期和不同物种的列表。每天有任意数量的移植手术,移植手术在任意的日子进行。你知道吗
考虑到以下移植:
[
{ 'datetime': '2019-07-01 10:00:00', 'species': ['Lettuce', 'Kale'] },
{ 'datetime': '2019-07-01 12:00:00', 'species': ['Basil', 'Kale', 'Chard'] },
{ 'datetime': '2019-07-01 15:00:00', 'species': ['Lettuce'] },
{ 'datetime': '2019-07-02 11:00:00', 'species': ['Spinach'] },
{ 'datetime': '2019-07-02 16:15:00', 'species': ['Lettuce'] },
{ 'datetime': '2019-07-05 09:00:00', 'species': ['Lettuce', 'Kale'] },
{ 'datetime': '2019-07-05 12:00:00', 'species': ['Arugula', 'Spinach'] },
]
我想要这些结果(如果page_size = 2
):
# page 1
[
{ 'date': '2019-07-01', 'species': ['Lettuce', 'Kale', 'Basil', 'Chard'] },
{ 'date': '2019-07-02', 'species': ['Spinach', 'Lettuce'] },
]
# page 2
[
{ 'date': '2019-07-05', 'species': ['Lettuce', 'Kale', 'Arugula', 'Spinach'] },
]
我尝试过的:
我现在要做的是查询不同的日期,抓取一页这些日期,再次查询那些日期的所有移植,然后序列化,就像这样:
class TransplantViewSet(viewsets.ModelViewSet):
model = Transplant
queryset = Transplant.objects.all()
serializer_class = GenericTransplantSerializer
lookup_field = 'pk'
# ...
@list_route(methods=('get'))
def by_date(self, request, *args, **kwargs):
# Annotate dates
date_qs = Transplants.objects.order_by('-datetime')\
.annotate(date=Trunc('datetime', 'day', output_field=DateField()))\
.values_list('date', flat=True)\
.distinct()
# Get a single page of dates
dates = paginator.paginate_queryset(dates_qs, request)
# Get matching transplants
transplants = Transplant.objects.filter(datetime__date__in=dates)\
.annotate(date=Trunc('datetime', 'day', output_field=DateField()))
# Build a dict formatted as
# { 'date_1': [t1, t2, ...], 'date_2': [t1, t2, ...], ... }
transplants_by_date = {}
for t in transplants:
transplants_by_date.setdefault(t.date, []).append(t)
# Transpose to a list of dicts in the format
# { 'date': 'date_1': 'species': [t1, t2, ...], ... }
transplants_by_date = [{'date': k, 'species': v} for k,v in transplants_by_date.items()]
# Serialize
serial = TransplantByDateSerializer(transplants_by_date,
many=many,
context={'request':request})
return Response(serial.data)
有没有不那么笨手笨脚的方法?这是可行的,但它会造成额外的数据库访问,而且性能不是很好(实际的模型和查询更复杂,在某种程度上得益于预取)。你知道吗
我曾尝试使用window w as (partition by date_part('day', datetime) order by datetime desc)
(用Django实现)这样的方法在一次数据库访问中完成,但我无法将结果转换成Model
实例,也无法避免滚动我自己的字典,如上所述。你知道吗
我愿意把我的DateTimeField
改成DateField
,如果这有帮助的话,因为在我实际的、更复杂的模型中,确切的时间是在别处捕捉到的。这个Transplant
模型更多的是对活动的总结。你知道吗
我使用的是django2.1.7、drf3.7.3和python3.6.8,如果这很重要的话,它们都运行在postgresql11之上。你知道吗
任何建议都将不胜感激!谢谢!你知道吗
目前没有回答
相关问题 更多 >
编程相关推荐