Django 모델 역모드

여러분, 안녕하세요.
Django를 사용할 때, 우리는 이 작업을 완성하는 코드를 작성하지만, 일부 코드는 우리가 모르는 과도한 계산이나 조작을 실행할 수 있습니다.이러한 작업은 실제 작업에서 유효하지 않거나 정반대일 수 있습니다.
여기서 저는 Django 모델 중의 일부 반모드를 언급할 것입니다.

A. Using len(queryset) instead of queryset.count()

  • Django의queryset은 평가가 지연되었다. 이것은 우리가 데이터와 상호작용을 하기 전에 데이터베이스에 있는 기록이 데이터베이스에서 읽히지 않는다는 것을 의미한다.
  • len(queryset)는 파이톤 해석기를 통해 응용 프로그램 단계에서 데이터베이스 기록 계수를 실행한다.이 점을 하려면 먼저 데이터베이스에서 모든 기록을 추출해야 한다. 이것은 계산량이 매우 큰 조작이다.
    그러나 queryset.count() 데이터베이스 단계에서 계수를 계산하고 계수만 되돌려줍니다.
  • 모델 번호Post:
    from django.db import models
    
    class Post(models.Model):
        author = models.CharField(max_length=100)
        title = models.CharField(max_length=200)
        content = models.TextField()
    
    만약 우리가 len(queryset)를 사용한다면, 이것은 SELECT * FROM post처럼 계산을 처리하고, 기록 목록 (queryset) 을 되돌려주고python 해석기가queryset의 길이를 계산합니다. 이것은 목록 데이터 구조와 유사합니다.많은 기록을 다운로드하는 것은 단지 길이를 검사하고 마지막에 버리기 위해서일 뿐이다. 얼마나 낭비하는가!그러나 우리가 읽는 길이를 기록해야 한다면 len(queryset) 유효할 수 있다.
    만약 우리가 queryset.count()를 사용한다면 데이터베이스 단계에서 SELECT COUNT(*) FROM post처럼 계산을 처리할 것이다.그것은 코드를 더욱 빨리 실행하고 데이터베이스 성능을 향상시켰다.

    B. Using queryset.count() instead of queryset.exists()

  • 우리는queryset의 길이를 검사하기 위해queryset.count()를 사용한다고 칭찬해 왔지만,queryset의 존재를 검사하려면 사용하면 성능이 떨어질 수 있습니다.
    동일한 모델Post에 대해 작성자Arjun가 쓴 댓글이 있는지 확인하고 싶을 때 다음과 같이 할 수 있습니다.
  • posts_by_arjun: Queryset = Post.objects.filter(author__iexact='Arjun')
    
    if posts_by_arjun.count() > 0:
        print('Arjun writes posts here.')
    else:
        print('Arjun doesnt write posts here.)
    
    posts_by_arjun.count() 데이터베이스 테이블의 각 행을 검색하는 SQL 작업을 수행합니다.그러나 If Arjun writes posts here or not ?에만 관심이 있다면 보다 효율적인 코드는 다음과 같습니다.
    posts_by_arjun: Queryset = Post.objects.filter(author__iexact='Arjun')
    
    if posts_by_arjun.exists():
        print('Arjun writes posts here.')
    else:
        print('Arjun doesnt write posts here.)
    
    posts_by_arjun.exists() 최소한 하나의 결과가 존재하는지 확인하는 브리 표현식을 되돌려줍니다.그것은 단지 가장 최적화된 방식으로 단일 기록을 읽을 뿐이다. (정렬 삭제, 사용자 정의 제거 select_related() 또는 distinct() 방법)
    또한queryset의 존재성/진실성을 이렇게 검사하는 것은 효과가 없다.
    posts_by_arjun: Queryset = Post.objects.filter(author__iexact='Arjun')
    
    if posts_by_arjun:
        print('Arjun writes posts here.')
    else:
        print('Arjun doesnt write posts here.)
    
    이는 아준의 게시물이 있는지 확인하는 데는 잘했지만, 더 많은 기록에 대해서는 계산량이 많았다.따라서 사용queryset.exists()을 권장하여 조회집의 존재성/진실성을 검사한다.

    C. Using signals excessively

  • Django 신호는 이벤트에 따라 작업을 촉발하기에 매우 적합하다.그러나 과도하게 사용해서는 안 되는 효과적인 사례가 있다.코드 라이브러리에서 신호의 어떤 대체 방안을 고려하여 그 대체에 대해 두뇌 폭풍을 일으키고 가능하다면 모델 자체에 신호 논리를 놓아 보세요.
  • 비동기적으로 실행되지 않습니다.백엔드 라인이나 작업 라인이 그것들을 실행하지 않습니다.만약 배경 스태프가 당신을 도와 일을 완성하게 하고 싶다면, 사용해 보세요. celery
  • 만약에 더 큰 프로젝트에서 일한다면 신호는 서로 다른 문서에 분산되어 회사에 막 가입한 사람에게 신호를 추적하기 어려울 것이다. 이것은 좋지 않다.비록django-debug-toolbar은 추적 촉발 신호에 어느 정도 도움이 된다.
  • 단독 모델Post에 쓴 기록을 저장하고 싶은 장면을 만듭니다.
    class PostWritings(models.Model):
        author = models.CharField(max_length=100, unique=True)
        posts_written = models.PositiveIntegerField(default=0)
    
    PostWritings 모델에 생성된 기록에 따라 자동으로 업데이트PostWritings 기록을 사용하려면 신호가 있거나 없는 상황에서 작업을 완성할 수 있는 몇 가지 방법이 있습니다.
    A.신호가 있다
    from django.db.models.signals import post_save
    from django.db.models import F
    from django.dispatch import receiver
    from .models import Post
    
    @receiver(sender=Post, post_save)
    def post_writing_handler(sender, instance, created, **kwargs):
    if created:
        writing, created = PostWritings.objects.get_or_create(author=instance.author)
        writing.update(posts_written=F('posts_written') + 1)
    
    B. 신호가 없어요.
    우리는 Post 모델을 덮어쓰는 save() 방법이 필요하다.
    from django.db import models
    from django.db.models import F
    
    class Post(models.Model):
        author = models.CharField(max_length=100)
        title = models.CharField(max_length=200)
        content = models.TextField()
    
        def save(self, *args, **kwargs:
            # Overridden method.
            author = self.author
            if self.id:
                writing, created = PostWritings.objects.get_or_create(author=author)
                writing.update(posts_written=F('posts_written') + 1)
            super(Post, self).save(*args, **kwargs)
    
    같은 작업은 신호가 없는 상황에서 완성할 수 있기 때문에 코드는 불필요한 사건의 촉발을 쉽게 추적하고 방지할 수 있다.
    만약 Post 방법이 읽을 수 없다고 생각하는 사람이 있다면, 코드를 분해하는 것은 항상 좋다.우리 하자.
    from django.db import models
    from django.db.models import F
    
    class Post(models.Model):
        author = models.CharField(max_length=100)
        title = models.CharField(max_length=200)
        content = models.TextField()
    
        def _update_post_writing(self, created=False, author=None):
            if author is not None and created:
                writing, created = PostWritings.objects.get_or_create(author=author)
                writing.update(posts_written=F('posts_written') + 1)
    
        def save(self, *args, **kwargs:
            # Overridden method.
            author = self.author
            created = self.id is None
            super(Post, self).save(*args, **kwargs)
            self._update_post_writing(created, author)
    
    보아하니 우리는 Django 모델의 일부 반모드를 어떻게 완화하는지 배운 것 같다.지금 초대해 주셔서 감사합니다.나는 곧 더 많은 Django에 관한 이야기를 계속할 것이다.
    너도 GitHub에서 나를 찾을 수 있다.그 전save()

    좋은 웹페이지 즐겨찾기