При использовании/вызове метода, вычисляющего queryset в другом методе, происходит многократное обращение к базе данных

Я работаю над проектом DRF, чтобы изучить модели ContentType. Я создал модель поста и модель комментария(ContentType), а затем добавил комментарии к посту. Все работало хорошо, пока я не добавил django-debug-tool и не продублировал запросы.

У меня есть следующие вопросы:

  1. I've defined a method(children) and property(total_replies) on the comment model. Since total_replies just calling children method and count the size of queryset. Will it result in hitting the database two or more times in case I use the children method in some other methods or property?
  2. If the database is hitting multiple times, what solution two improve performance?
  3. After adding select_related the num of queries has been reduced drastically. Before using select_related enter image description here

После использования select_related enter image description here Хорошо ли использовать select_related во всех местах, где использовался Foreignkey?

Приложение к блогу

models.py

class Post(models.Model):
    title = models.CharField(verbose_name=_("Post Title"), max_length=50)
    content = models.TextField()
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='blog_posts')
    category = models.ForeignKey(Category, on_delete=models.CASCADE)

    def __str__(self):
        return self.title

    @property
    def comments(self):
        instance = self
        #qs = Comment.objects.filter_by_instance(instance) #before
        qs = Comment.objects.select_related('user').filter_by_instance(instance)
        return qs

    @property
    def get_content_type(self):
        instance = self
        content_type = ContentType.objects.get_for_model(instance.__class__)
        return content_type


serializers.py
class PostSerializer(serializers.ModelSerializer):
    author = UserPublicSerializer(read_only=True)
    status_description = serializers.ReadOnlyField(source='get_status_display')

    class Meta:
        model = Post
        fields = (
            'url', 'id', 'title', 'author',
            'content', 'category', 'total_likes',
        )


class PostDetailSerializer(serializers.ModelSerializer):
    author = UserPublicSerializer(read_only=True)
    status_description = serializers.ReadOnlyField(source='get_status_display')
    comments = serializers.SerializerMethodField()

    class Meta:
        model = Post
        fields = (
            'url', 'id', 'title', 'author', 'content',
            'category', 'comments', 'total_likes'
        )


    def get_comments(self, obj):
        request = self.context.get('request')
        comments_qs = Comment.objects.filter_by_instance(obj)
        comments = CommentSerializer(comments_qs, many=True, context={'request':request}).data
        return comments


class PostListCreateAPIView(generics.ListCreateAPIView):
    serializer_class = serializers.PostSerializer
    # queryset = Post.objects.all().order_by('-id') # before
    queryset = Post.objects.select_related('author').order_by('-id')
    name = 'post-list'
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]

    def perform_create(self, serializer):
        serializer.save(author=self.request.user)

class PostRetrieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView):
    serializer_class = serializers.PostDetailSerializer
    # queryset = Post.objects.all().order_by('-id') # before
    queryset = Post.objects.select_related('author').order_by('-id')
    name = 'post-detail'
    permission_classes = [permissions.IsAuthenticatedOrReadOnly, account_permissions.IsStaffOrAuthorOrReadOnly]

    def perform_update(self, serializer):
        serializer.save(author=self.request.user)

Комментарий приложения

Заранее спасибо.

Это именно то, что говорится в документации django о select_related :

"Возвращает QuerySet, который будет "следовать" за отношениями "иностранный ключ", выбирая дополнительные данные связанных объектов при выполнении запроса. Это увеличение производительности, которое приводит к одному более сложному запросу, но означает, что последующее использование отношений "иностранный ключ" не потребует запросов к базе данных."

Они описывают select_related как нечто сложное, но хорошее с точки зрения транзакционной стоимости БД.

Вернуться на верх