如果你有大量数据,使用嵌套关系或PrimaryKeyRelated字段会更好吗?
我有一个关系很深的模特 为简单起见,我没有添加colums。
型号:
USECASE:
问题:
我想跟踪每个锻炼计划的进展>锻炼>行使。 因此,随着时间的推移,用户可能已经完成了数十次锻炼,因此如果数据库中已有数百套,那么用户就可以完成。
如果我现在使用嵌套的关系,我可能会加载大量我不需要的数据。 但是如果我使用PrimaryKeyRelatedFields,我必须分别加载我需要的所有数据,这意味着我的前端会有更多的努力。
在这种情况下,首选哪种方法?
修改
如果我使用PrimaryKeyRelatedFields,我如何区分是否Workoutplan中的锻炼是一个带有主键的数组或带有加载对象的数组?
答案 0 :(得分:1)
如果您使用PrimaryKeyRelatedField,您将有一个很大的重载来请求前端的必要数据
在您的情况下,我将使用您想要的字段创建特定的序列化程序(使用Meta.fields
属性)。因此,您不会加载不必要的数据,并且前端不需要从后端请求更多数据。
如果您需要更多详细信息,我可以编写示例代码。
答案 1 :(得分:0)
我将在一秒钟内讨论有关序列化器的问题,但首先要澄清一下。将重复模型作为锻炼/完成锻炼,设置/完成集,......?
的目的是什么为什么不......
class Workout(models.Model):
#...stuff...
finished = models.DateTimeField(null=True, blank=True)
#...more stuff...
然后,您可以在锻炼完成后设置完成日期。
现在,关于这个问题。我建议你考虑用户互动。您想要填充前端的哪些部分?数据如何相关以及用户如何访问它?
您应该考虑使用DRF查询哪些参数。您可以发送日期并期望在特定日期完成锻炼:
// This example is done in Angular, but you get the point...
var date= {
'day':'24',
'month':'10',
'year':'2015'
};
API.finishedWorkout.query(date).$promise
.then(function(workouts){
//...workouts is an array of workout objects...
});
...视图集
class FinishedWorkoutViewset(viewsets.GenericAPIView,mixins.ListModelMixin):
serializer_class = FinishedWorkOutSerializer
queryset = Workout.objects.all()
def list(self, request):
user = self.request.user
day = self.data['day'];
month = self.data['month'];
year = self.data['year'];
queryset = self.filter_queryset(self.get_queryset().filter(finished__date=datetime.date(year,month,day)).filter(user=user))
page = self.paginate_queryset(queryset)
serializer = self.get_serializer(queryset, many=True)
return response.Response(serializer.data)
然后您的 FinishedWorkoutSerializer 可以为该特定类型的查询提供您想要的任何字段。
这会为您留下一堆非常具体的网址,但这些网址并不是很好,但您可以使用特定的序列化程序进行这些交互,并且您还可以动态更改过滤器,具体取决于具体内容参数位于self.data
。
您可能希望根据所调用的方法进行不同的过滤,比如说您只想列出活动练习,但如果用户查询特定练习,您希望他能够访问它(注意Exercise对象应该有一个名为" active")的models.BooleanField
属性。
class ExerciseViewset(viewsets.GenericViewSet, mixins.RetrieveModelMixin, mixins.ListModelMixin):
serializer_class = ExerciseSerializer
queryset = Exercise.objects.all()
def list(self, request):
queryset = self.filter_queryset(self.get_queryset().filter(active=True))
page = self.paginate_queryset(queryset)
serializer = self.get_serializer(queryset, many=True)
return response.Response(serializer.data)
现在,您可以在同一网址上显示不同的对象,具体取决于操作。它更接近您的需求,但您仍然使用相同的序列化程序,因此如果您需要retrieve()
上的大型嵌套对象,您还会得到一堆当你list()
。
为了保持列表简短和嵌套细节,您需要使用不同的序列化程序。
我们假设您只想发送练习'列出时会pk
和name
属性,但无论何时查询练习,您都不会发送所有相关的" Set"在" WorkoutSets" ...
# Taken from an SO answer on an old question...
class MultiSerializerViewSet(viewsets.GenericViewSet):
serializers = {
'default': None,
}
def get_serializer_class(self):
return self.serializers.get(self.action, self.serializers['default'])
class ExerciseViewset(MultiSerializerViewSet, mixins.RetrieveModelMixin, mixins.ListModelMixin):
queryset = Exercise.objects.all()
serializers = {
'default': SimpleExerciseSerializer,
'retrieve': DetailedExerciseSerializer
}
然后你的serializers.py看起来有点像......
#------------------Exercise
#--------------------------Simple List
class SimpleExerciseSerializer(serializers.ModelSerializer):
class Meta:
model Exercise
fields = ('pk','name')
#--------------------------Detailed Retrieve
class ExerciseWorkoutExerciseSetSerializer(serializers.ModelSerializer):
class Meta:
model Set
fields = ('pk','name','description')
class ExerciseWorkoutExerciseSerializer(serializers.ModelSerializer):
set_set = ExerciseWorkoutExerciseSetSerializer(many=True)
class Meta:
model WorkoutExercise
fields = ('pk','set_set')
class DetailedExerciseSerializer(serializers.ModelSerializer):
workoutExercise_set = exerciseWorkoutExerciseSerializer(many=True)
class Meta:
model Exercise
fields = ('pk','name','workoutExercise_set')
我只是抛弃在您的模型中可能没有意义的用例和属性,但我希望这有用。
P.S。;看看我到底是如何得到Java的:p" ExcerciseServiceExcersiceBeanWorkoutFactoryFactoryFactory"