型号
class Challenge(models.Model):
name = models.CharField(...)
version = models.IntegerField(...)
class Workout(models.Model):
name = models.CharField(...)
version = models.IntegerField(...) # this field may not exist
# this is a through table
class ChallengeWorkoutRelation(models.Model):
challenge_id = models.IntegerField() # for some reason, this is IntegerField, not ForeignKey
workout_id = models.IntegerField() # for some reason, this is IntegerField, not ForeignKey
version = models.IntegerField(default=0)
我想让所有锻炼都属于一项挑战:
for relation in ChallengeWorkoutRelation.objects.filter(challenge_id=challenge.pk, version=challenge.version):
workout = Workout.objects.get(id=relation.workout_id)
# do something with workout...
# another version
# workout = Workout.objects.get(id=relation.workout_id, version=challenge.version)
我可以优化这段代码以获得更高的性能吗?
是的,您可以通过减少数据库查询次数来优化代码以提高性能。关键是尽量减少访问数据库的次数。在您的代码中,您当前正在为与挑战相关的每个锻炼进行单独的数据库查询,这可能会导致大量的数据库查询。
您可以使用 select_lated 或 prefetch_lated 查询集方法以更有效的方式检索相关对象以及 ChallengeWorkoutRelation 查询。在您的情况下,由于 ChallengeWorkoutRelation 具有 Challenge 和 Workout 的外键,因此您可以使用 select_lated 在单个查询中与 ChallengeWorkoutRelation 一起获取相关的 Workout 对象。
这是使用 select_lated 的优化版本:
relations =
ChallengeWorkoutRelation.objects.filter(challenge_id=challenge.pk,
version=challenge.version).select_related('workout')
for relation in relations:
workout = relation.workout
# do something with workout...
这样,您可以在单个查询中获取所有相关的 Workout 对象,而不是为每个关系进行单独的查询。
或者,如果您有大量关系,您可能需要考虑使用 prefetch_lated:
relations =
ChallengeWorkoutRelation.objects.filter(challenge_id=challenge.pk,
version=challenge.version).prefetch_related('workout')
for relation in relations:
workout = relation.workout
# do something with workout...
prefetch_lated 更适合处理反向外键关系或者有大量相关对象时。
根据您的具体用例和性能测试在 select_lated 和 prefetch_lated 之间进行选择。