DRF中如何让ViewSet返回Wallet关联的BudgetEntry收支数据?
问题
我开发了一个DRF应用,其中一个WalletInstance(钱包)可关联多条BudgetEntry(收支记录)。调用ViewSet接口时,返回数据格式如下:
[ { "id": "d458196e-49f1-42db-8bc2-ee1dba438953", "owner": 1, "viewable": [], "entry": [] } ]
目前entry字段为空数组,请问如何获取并展示该字段的具体内容?
相关模型代码
class Category(models.Model): name = models.CharField(max_length=20, unique=True) def __str__(self): return self.name class BudgetEntry(models.Model): STATE= [ ('income','income'), ('expenses','expenses'), ] amount = models.IntegerField() entry_type = models.CharField(max_length=15, choices=STATE, null=True) entry_category = models.ForeignKey(Category, null=True, blank=True, on_delete=models.SET_NULL) class WalletInstance(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True) owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='owner', on_delete=models.CASCADE) viewable = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='can_view', blank=True) entry = models.ManyToManyField(BudgetEntry, related_name='BudgetEntry', blank=True)
Serializers.py代码
class BudgetEntrySerializer(serializers.ModelSerializer): class Meta: model = BudgetEntry fields = '__all__' class WalletInstanceSerializer(serializers.ModelSerializer): owner = serializers.ReadOnlyField(source='owner.id') class Meta: model = WalletInstance fields = '__all__'
Views.py代码
class WalletViewset(viewsets.ModelViewSet): permission_classes = [IsAuthenticated] serializer_class = WalletInstanceSerializer def get_queryset(self): user_id = self.request.user.id available = WalletInstance.objects.filter( Q(owner=user_id) ) return available
解决方案
1. 修改序列化器,嵌套收支记录序列化逻辑
当前WalletInstanceSerializer中,entry字段默认仅返回关联对象的ID列表。要展示完整的收支记录内容,需在序列化器中嵌套BudgetEntrySerializer:
修改WalletInstanceSerializer代码:
class WalletInstanceSerializer(serializers.ModelSerializer): owner = serializers.ReadOnlyField(source='owner.id') # 嵌套BudgetEntrySerializer,many=True适配多对多关系 entry = BudgetEntrySerializer(many=True, read_only=True) class Meta: model = WalletInstance fields = '__all__'
2. 优化查询避免N+1性能问题
直接嵌套序列化器会导致每个WalletInstance单独查询一次entry数据,引发N+1查询问题。可在get_queryset中通过prefetch_related预加载关联数据:
修改WalletViewset的get_queryset方法:
from django.db.models import Q class WalletViewset(viewsets.ModelViewSet): permission_classes = [IsAuthenticated] serializer_class = WalletInstanceSerializer def get_queryset(self): user_id = self.request.user.id available = WalletInstance.objects.filter( Q(owner=user_id) ).prefetch_related('entry') # 预加载entry关联数据 return available
验证效果
修改完成后重新调用接口,entry字段会展示每条收支记录的完整信息,示例返回格式如下:
[ { "id": "d458196e-49f1-42db-8bc2-ee1dba438953", "owner": 1, "viewable": [], "entry": [ { "id": 1, "amount": 1000, "entry_type": "income", "entry_category": 1 }, { "id": 2, "amount": 500, "entry_type": "expenses", "entry_category": 2 } ] } ]
内容的提问来源于stack exchange,提问作者rafaelHTML
相关产品推荐
相关产品推荐

