Django REST framework如何根据当前时间返回物品已预订/空闲状态
实现方案
首先修正你现有代码的两处笔误:
Items模型中选项变量名不匹配:定义的是ITEMS_CATEGORIES,字段调用时写的是ITEM_CATEGORIESBooking模型的item外键关联对象错误,你写的Subsystem应该是Items
方案1:物品列表展示状态(适配你的需求场景)
你需要展示所有物品的当前状态,因此直接针对Items模型做状态判断和序列化即可:
步骤1:修改Items模型增加状态判断逻辑
from django.utils import timezone class Items(models.Model): ITEMS_CATEGORIES=( ('item-1', 'item-1'), ('item-2', 'item-2'), ('item-3', 'item-3'), ('item-4', 'item-4'), ('item-5', 'item-5'), ) category = models.CharField(max_length=10, choices=ITEMS_CATEGORIES) # 原max_length=5不够,item-x长度为6 def __str__(self): return self.category # 新增状态属性 @property def current_status(self): now = timezone.now() # 判断当前物品是否有正在生效的预约 has_active_booking = self.booking_set.filter( check_in__lte=now, check_out__gte=now ).exists() return "booked(已预订)" if has_active_booking else "free(空闲)"
步骤2:编写物品状态序列化器
from rest_framework import serializers from .models import Items class ItemStatusSerializer(serializers.ModelSerializer): status = serializers.CharField(source='current_status', read_only=True) # 可选:增加当前预约人字段 current_booking_user = serializers.SerializerMethodField(read_only=True) class Meta: model = Items fields = ('id', 'category', 'status', 'current_booking_user') def get_current_booking_user(self, obj): now = timezone.now() active_booking = obj.booking_set.filter( check_in__lte=now, check_out__gte=now ).first() return active_booking.user if active_booking else None
步骤3:视图调用示例
from rest_framework import viewsets from .models import Items from .serializers import ItemStatusSerializer class ItemStatusViewSet(viewsets.ReadOnlyModelViewSet): queryset = Items.objects.all() serializer_class = ItemStatusSerializer
返回数据示例:
[ { "id": 1, "category": "item-1", "status": "free(空闲)", "current_booking_user": null }, { "id": 2, "category": "item-2", "status": "booked(已预订)", "current_booking_user": "张三" } ]
方案2:预约列表附带物品状态
如果你确实需要在预约记录的序列化结果中附加对应物品的当前状态,按以下实现:
from rest_framework import serializers from django.utils import timezone from .models import Booking class BookingSerializer(serializers.ModelSerializer): item_current_status = serializers.SerializerMethodField(read_only=True) class Meta: model = Booking fields = ('item','check_in','check_out', 'user', 'item_current_status') def get_item_current_status(self, obj): now = timezone.now() return "booked(已预订)" if obj.check_in <= now <= obj.check_out else "free(空闲)"
注意:不要直接用
datetime.datetime.now(),Django开启时区支持时这个方法返回的是无时区信息的时间,和数据库存储的带时区时间对比会报错,必须用django.utils.timezone.now()获取当前时间。
内容的提问来源于stack exchange,提问作者lee thunder
相关产品推荐
相关产品推荐

