简体   繁体   中英

DRF select_related and prefetch_related doesn't work

I'm try to decrease query counts for using prefetch_related and select_related . However, it seems doesn't work.

in Match Model have 5 ForeignKey fields, so when i get the query counts it will return 5. Also when i delete def get_queryset method in MatchDetailAPIView . The Api still work. ( eg 127.0.0.1:8000/game/match/match-1 is working whether or not the get_queryset method.

I can't find where I'm doing wrong.

Models.py

    class Game(models.Model):
       name = models.CharField(max_length=255)
        ...

    class Match(models.Model):
        name = models.TextField(blank=False, null=False)
        game = models.ForeignKey(Game, on_delete=models.SET_NULL, null=True)
        tournament = models.ForeignKey(Tournament, on_delete=models.SET_NULL, null=True, blank=True)
        ....

serializers.py

 class MatchSerializer(serializers.ModelSerializer):

    class Meta:
        model = Match
        fields = '__all__'
        #exclude = ['participant', ]

views.py

class MatchDetailAPIView(RetrieveAPIView):

serializer_class = MatchSerializer

def get_queryset(self):
    queryset =Match.objects.all().prefetch_related('game_id')
    return queryset

def get_object(self):
    gameslug = self.kwargs.get('gameslug')
    slug = self.kwargs.get('slug')
    # find the user
    game = Game.objects.get(slug=gameslug)

    return Match.objects.get(slug=slug, game__slug=game.slug)

def get_serilizer_context(self, *args, **kwargs):
    return {'request': self.request}

You should use select_related for ForeignKey fields, since prefetch_related does the joining in Python, and select_related creates an SQL join.

You should also refer to the relationship by it's name, not the id of the ForeignKey ('game_id' vs. 'game'):

def get_queryset(self):
    queryset =Match.objects.all().select_related('game')
    return queryset

As mentioned in django docs , select_related should be used for foeign-key relationships. Also for RetrieveAPIView override the get method.

def get(self, request, *args, **kwargs):
    gameslug = self.kwargs.get('gameslug')
    slug = self.kwargs.get('slug')
    game = Game.objects.get(slug=gameslug)

    return Match.objects.filter(slug=slug, game__slug=gameslug).select_related('game').first()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM