logo
Search검색어를 포함하는 게시물들이 최신순으로 표시됩니다.
    Table of Contents
    [Django] shell_plus에서의 CRUD

    이미지 보기

    [Django] shell_plus에서의 CRUD

    • 22.03.08 작성

    • 22.03.09 수정

    • 읽는 데 8

    TOC

    CRUD

    • 대부분의 컴퓨터 소프트웨어가 가지는 기본적인 데이터 처리 기능
    • Create(생성), Read(읽기), Update(갱신), Delete(삭제)

    Create

    Create 1 : 인스턴스, 데이터 추가, 저장 따로

    // article 인스턴스를 Article 클래스에서 제작
    In [4]: article = Article()
    
    // 아직 DB에는 반영되지 않은 것
    In [9]: article
    Out[9]: <Article: Article object (None)>
    
    // instance에 데이터가 없는 것
    In [10]: article.title
    Out[10]: ''
    
    // 데이터(property)를 추가
    In [11]: article.title = 'first'
    
    In [12]: article.content = 'test'
    
    // 역시 아직도 DB에는 반영이 안 되었음
    In [13]: article
    Out[13]: <Article: Article object (None)>
    
    // save() : 현재 설정된 값들이 DB에 반영!! ⭐
    In [14]: article.save()
    
    // DB에 반영이 되었다. 그냥 인스턴스를 shell에 입력하면 PK(id)가 함께 나옴
    In [15]: article
    Out[15]: <Article: Article object (1)>
    

    위의 과정으로 인스턴스를 생성, 정의, 저장하여 DB에 반영까지 할 수 있다.


    image

    DB에 하나의 record가 table에 저장되었음을 확인


    Create 2 : 인스턴스 생성할 때 데이터 함께 생성, 저장은 따로

    In [1]: article = Article(title='second', content='django!!')
    
    In [2]: article.save()
    

    instance를 정의할 때 class 내에 property를 함께 정의


    image

    DB에 잘 반영되었다.


    Create 3 : 인스턴스 생성, 데이터, 저장 한 번에

    In [3]: Article.objects.create(title='third', content='django~~')
    Out[3]: <Article: Article object (3)>
    

    QuerySet API - create()를 사용


    image

    역시 DB에 잘 반영되었다.


    save() method

    • 객체를 DB에 저장
    • 데이터 생성 시 save()를 호출하기 전에는 객체의 ID값을 알 수 없다.
    • ID 값은 django가 아니라 DB에서 계산되기 때문
    • 단순히 model을 instance화하는 것은 DB에 영향을 미치지 않기 때문에 반드시 save() 필요

    __str__(self) method

    __str__(self) 정의 전

    In [1]: article = Article.objects.create(title='str test', content='str test~~')
    
    In [2]: article
    Out[2]: <Article: Article object (19)>
    

    pk인 id가 object의 고유 번호를 함께 출력할 뿐, 무슨 정보인지 알 수가 없다.


    __str__(self) 정의

    # models.py
    
    class Article(models.Model):
        title = models.CharField(max_length=10)
        content = models.TextField()
        created_at = models.DateTimeField(auto_now_add=True)
        updated_at = models.DateTimeField(auto_now=True)
        
        def __str__(self):
            return self.title
    
    • 표준 파이썬 클래스의 메소드인 str()을 정의
    • 각각의 object가 사람이 읽을 수 있는 문자열을 return하도록 할 수 있다.
    • 작성/저장 후 반드시 shell_plus를 재시작해야 반영

    __str__(self) 정의 후

    In [1]: article = Article.objects.create(title='str test', content='str test~~')
    
    In [2]: article
    Out[2]: <Article: str test>
    

    title로 instance가 표시되어 어떤 record인지 판별이 쉬워졌다.


    QuerySet과 List

    • article을 Article의 objects 모두로 지정하면 list 형식으로 저장
    • indexing, slicing, for문 등 list 자료형의 조작이 모두 가능
    In [1]: Article.objects.all()
    Out[1]: <QuerySet [<Article: first>, <Article: second>, <Article: third>]>
    
    In [2]: article = Article.objects.all()
    
    In [3]: article[0]
    Out[3]: <Article: first>
    
    In [4]: article[1:]
    Out[4]: <QuerySet [<Article: second>, <Article: third>]>
    
    In [5]: type(article)
    Out[5]: django.db.models.query.QuerySet
    
    In [6]: for a in article:
       ...:     print(a.title)
       ...: 
    first
    second
    third
    

    READ

    all()

    • 현재 QuerySet의 복사본을 반환
    • QuerySet : 모든 인스턴스의 집합
    In [7]: Article.objects.all()
    Out[7]: <QuerySet [<Article: first>, <Article: second>, <Article: third>]>
    

    get()

    • ClassName.Manager.get(lookup_key=lookup_value) 형식

    • 주어진 lookup 매개변수와 일치하는 객체 변환

    • 위와 같은 특징 때문에 PK와 같이 고유성(unique)을 보장하는 조회에서 사용

    • lookup 매개변수는 2개 이상 사용 가능

    image

    content가 django!!로 중복된 상황을 만들기 위해 위와 같이 DB를 바꿔 등록해보았다.

    In [1]: Article.objects.get(content='django!!', title='second')
    Out[1]: <Article: second>
    

    오류 발생 예시

    • DoesNotExist 예외 : 객체를 찾을 수 없을 때
    • MultipleObjectReturned 예외 : 둘 이상의 객체를 찾았을 때
    // 가져오는 key가 없는 경우
    In [1]: article = Article.objects.get(pk=100)
    DoesNotExist: Article matching query does not exist.
    
    // 가져오는 lookup 조건에 해당하는 object가 2개 이상인 경우
    In [2]: Article.objects.get(content='django!!')
    MultipleObjectsReturned: get() returned more than one Article -- it returned 2!
    

    filter()

    • 주어진 lookup 매개변수와 일치하는 객체를 포함하는 새 QuerySet 반환

    • all() querySet API처럼 python에서 list로 처리 가능

    중요⭐ get()은 객체 하나만 조회하며 객체 자체를 반환, filter()는 여러 개의 객체를 리스트로 반환하며, 한 개를 반환하더라도 리스트에 담아 반환

    In [3]: Article.objects.filter(content="django!!")
    Out[3]: <QuerySet [<Article: second>, <Article: third>]>
    
    In [4]: Article.objects.filter(title='first')
    Out[4]: <QuerySet [<Article: first>]>
    

    Update

    # Article의 object 중 pk가 5인 object를 찾아 article에 저장
    In [6]: article = Article.objects.get(pk=5)
    
    # article의 title 검색
    In [7]: article.title
    Out[7]: 'first'
    
    # article의 title을 'byebye'로 갱신
    In [8]: article.title = 'byebye'
    
    # article을 DB에 저장/반영
    In [9]: article.save()
    
    # article의 title 갱신 확인
    In [10]: article.title
    Out[10]: 'byebye'
    
    image
    • id(pk)가 5인 record의 title이 'first'에서 'byebye'로 갱신
    • updated_at도 수정 일시로 갱신

    Delete : delete()

    • QuerySet의 모든 행에 대해 SQL 삭제 쿼리를 수행
    • 삭제된 객체 수와 객체 유형당 삭제 수가 포함된 딕셔너리 반환
    # pk가 5인 record를 article에 저장
    In [11]: article = Article.objects.get(pk=5)
    
    # article을 제거하면 mapping된 record도 제거
    In [12]: article.delete()
    Out[12]: (1, {'articles.Article': 1})
    
    # pk가 5인 record 조회, DoesNotExist 에러 발생
    In [13]: Article.objects.get(pk=5)
    DoesNotExist: Article matching query does not exist.
    
    image
    • pk가 5인 record가 실제로 제거됨을 확인 가능

    Field lookups

    • 조회 시 특정 조건을 지정
    • QuerySet 메서드 filter(), exclude() 미치 get()에 대한 키워드 인수로 지정
    • underbar 2개로 작성('__')
    • 사용 예시
      • Article.objects.filter(pk__gt=6) : pk가 6 이상인 record
      • Article.objects.filter(content__contains='ja') : content가 'ja'를 포함하는 record
    In [15]: Article.objects.filter(pk__gt=6)
    Out[15]: <QuerySet [<Article: third>]>
    
    In [16]: Article.objects.filter(content__contains='ja')
    Out[16]: <QuerySet [<Article: second>, <Article: third>]>
    

    QuerySet API

    profile

    FE Developer 박승훈

    노력하는 자는 즐기는 자를 이길 수 없다