如何在Django REST Framework同应用中实现跨模型数据提交与读取
一对多关联模型的提交与只读计算数据实现
需求:通过/returns端点提交BedNightReturn数据,/assessments端点以只读方式获取包含计算字段的评估数据。
1. 模型定义
class BedNightReturn(models.Model): room_type = models.CharField(max_length=50) number_of_rooms = models.PositiveSmallIntegerField() price_per_night = models.DecimalField(max_digits=10, decimal_places=2) days_in_month = models.PositiveSmallIntegerField() class Meta: verbose_name = 'BedNightReturn' verbose_name_plural = 'BedNightReturns' def __str__(self): return f'{self.room_type}' class BedNightReturnAssessment(models.Model): assessment = models.ForeignKey(BedNightReturn, related_name = "assessments", on_delete=models.CASCADE) class Meta: verbose_name = 'BedNightReturnAssessment' verbose_name_plural = 'BedNightReturnAssessments' def __str__(self): return f'{self.assessment.room_type}' @property def potential_turnover(self) -> float: days_in_month = 30 return float(days_in_month) * float(self.assessment.number_of_rooms) * float(self.assessment.price_per_night) @property def actual_turnover(self) -> float: return float(self.assessment.days_in_month) * float(self.assessment.number_of_rooms) * float(self.assessment.price_per_night)
2. 序列化器定义
class BedNightReturnSerializer(ModelSerializer): class Meta: model = BedNightReturn fields = ( 'id', 'room_type', 'number_of_rooms', 'price_per_night', 'days_in_month', ) class BedNightReturnAssessmentSerializer(ModelSerializer): assessment = BedNightReturnSerializer() potential_turnover = ReadOnlyField() actual_turnover = ReadOnlyField() class Meta: model = BedNightReturnAssessment fields = ( 'id', 'assessment', 'potential_turnover', 'actual_turnover', )
3. 视图定义
调整评估视图为只读模式,确保/assessments端点仅支持查询操作:
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet class BedNightReturnViewSet(ModelViewSet): queryset = BedNightReturn.objects.all() serializer_class = BedNightReturnSerializer class BedNightReturnAssessmentViewSet(ReadOnlyModelViewSet): queryset = BedNightReturnAssessment.objects.all() serializer_class = BedNightReturnAssessmentSerializer
4. URL配置
from django.urls import include, path from rest_framework import routers from bednightlevy.views import ( BedNightReturnAssessmentViewSet, BedNightReturnViewSet, ) router = routers.DefaultRouter(trailing_slash = False) router.register('returns', BedNightReturnViewSet, basename="bednight") router.register('assessments', BedNightReturnAssessmentViewSet, basename='bednight_assessment') urlpatterns = [ path('',include(router.urls)), ]
补充优化说明
- 自动生成评估记录:当前提交
BedNightReturn后不会自动创建对应的评估记录,若需要自动关联,可在BedNightReturn的save方法中添加逻辑:
class BedNightReturn(models.Model): # 原有字段及方法... def save(self, *args, **kwargs): super().save(*args, **kwargs) # 仅在无关联评估记录时创建 if not self.assessments.exists(): BedNightReturnAssessment.objects.create(assessment=self)
内容的提问来源于stack exchange,提问作者Lodyne Mark
相关产品推荐
相关产品推荐

