TIL no.66 - Django - Basic - 19 - 데이터 조회 / 수정

박준규·2019년 10월 29일
5

Django

목록 보기
26/30

Django의 간단한 Model을 구현한 뒤에 DB에 데이터를 저장하고 저장한 데이터를 다루는 방법에 대해 포스팅하겠습니다.

1. Model 구현

from django.db import models

class Restaurant(models.Model): # Restaurant 라는 상점을 나타내는 모델을 정의
    name = models.CharField(max_length=30)  # 이름
    address = models.CharField(max_length=200)  # 주소

    created_at = models.DateTimeField(auto_now_add=True)  # 글 작성 시 (이 모델의 데이터(레코드) 저장 시) 생성 시각
    updated_at = models.DateTimeField(auto_now=True)  # 저장된 레코드 수정 시 수정 시각

위 처럼 간단한 Model을 구현하고
migrate까지 해줍니다.

Django shell에서 데이터를 다뤄보겠습니다.

2. 데이터 조회

Django Shell을 실행합니다.

python manage.py shell
>> from third.models import Restaurant
>> Restaurant(name=’Deli Shop’, address=’Gangnam’).save()
>> Restaurant(name=’Korean Food’, address=’Gangbuk’).save()
>> Restaurant(name=’Sushi’, address=’Gangbuk’).save()

3개의 record를 생성해줍니다.

2-1. all()

이제 조회해보겠습니다.

>> Restaurant.objects.all()
#Restaurant에 해당하는 데이터를 QuerySet의 형태로 모두 가져옵니다. 
>> Restaurant.objects.all().values()
#values() 메서드를 사용해 실제 데이터에 들어있는 정보를 눈으로 확인할 수 있습니다.

2-2. order_by

정렬 순서를 변경할 수 있습니다.

>> Restaurant.objects.order_by('-created_at').values()  # 최신순
>> Restaurant.objects.order_by('name').values()  #  이름순

그냥 'created_at'으로 정렬하게 되면 작은 값부터 오름차순으로 정렬하게 되는데 그러면 가장 오래된 데이터부터 정렬됩니다.
-를 붙이면 역순으로 정렬하게 됩니다.

2-3.get()

primary key를 이용해서 하나의 record를 불러올 수 있습니다.
get()메서드는 QuerySet이 아니라 Python객체 형태를 반환합니다.
그렇기 때문에 .(dot notation)으로 value에 접근할 수 있습니다.

>> Restaurant.objects.get(pk=1).name
>> Restaurant.objects.get(pk=2).address
>> item = Restaurant.objects.get(pk=3)
>> item.name

get메서드를 통해 name이 'Deli Shop'인 record를 불러오는 것도 가능합니다.

2-4. filter(), exclude()

하지만, 보통 데이터를 조회할 때는 filter 혹은 exclude 메서드를 사용합니다.
이 두 메서드들은 특정 조건에 부합하는 혹은 부합하지 않는 데이터들을 조회합니다.

>> Restaurant.objects.filter(name='Deli Shop').values()
<QuerySet [{'id': 1, 'name': 'Deli Shop', 'address': 'Gangbuk', 'created_at': datetime.datetime(2018, 12, 5, 22, 18, 34, 950381, tzinfo=<UTC>), 'updated_at': datetime.datetime(2018, 12, 5, 22, 48, 50, 482695, tzinfo=<UTC>)}]>

>>  Restaurant.objects.exclude(name='Sushi').values()
<QuerySet [{'id': 1, 'name': 'Deli Shop', 'address': 'Gangbuk’, 'created_at': datetime.datetime(2018, 12, 5, 22, 18, 34, 950381, tzinfo=<UTC>), 'updated_at': datetime.datetime(2018, 12, 5, 22, 48, 50, 482695, tzinfo=<UTC>)}, {'id': 2, 'name': 'Korean Food', 'address': 'Gangnam', 'created_at': datetime.datetime(2018, 12, 5, 22, 21, 52, 35871, tzinfo=<UTC>), 'updated_at': datetime.datetime(2018, 12, 5, 22, 21, 52, 35921, tzinfo=<UTC>)}]>

2-5.chaning

QuerySet은 실제로 DB에서 데이터를 가져온 것은 아닙니다. 그렇기 때문에 chaining이 가능합니다.

>>> query = Restaurant.objects.exclude(name='Sushi')
>>> query = query.exclude(address='Gangnam')
>>> query.values() # 이 시점에 쿼리 실행
<QuerySet [{'id': 2, 'name': 'Korean Food', 'address': 'Gangbuk', 'created_at': datetime.datetime(2018, 12, 5, 22, 21, 52, 35871, tzinfo=<UTC>), 'updated_at': datetime.datetime(2018, 12, 5, 22, 55, 56, 81772, tzinfo=<UTC>)}]>

2-6.pagination

데이터가 많은 경우, 페이지를 나눠서 조회합니다. 이를 paging혹은 pagination이라고 표현합니다.

>>>  Restaurant.objects.all()[0:1]  # start 0, end 1

record를 읽기 시작하는 위치, record를 읽을 마지막 값
slicing처럼 받아들이면 편합니다.

2-7. Field Lookup

django orm의 field lookup을 사용해보겠습니다.

Restaurant.objects.filter(name=’Korean Food’)

위의 명령은 다음과 같습니다.

Restaurant.objects.filter(name__exact=’Korean Food’)

여태까지 __exact를 사용한 것과 같은 것입니다.

이렇게 under score 2개와 조건을 붙이는 것이 field lookup입니다.

몇가지 조건 키워드들을 알아보겠습니다.

  • contains
>> from third.models import Restaurant
>> Restaurant.objects.filter(name__contains=’Korea’).values()
  • gt, gte, lt, lte
>> Restaurant.objects.filter(created_at__lt='2018-01-01 00:00:00').values()
>> Restaurant.objects.filter(created_at__gt='2018-01-01 00:00:00').values()

lt는 less than
gt는 greater than의 약어입니다.

즉, 조건보다 작은 것, 조건보다 큰 것을 조회할 때 사용합니다.

뒤에 e는 equalty를 뜻합니다.

  • startswith, istartswith, endswith, iendswith
>> Restaurant.objects.filter(name__startswith='Korea').values()
>> Restaurant.objects.filter(name__endswith='Food').values()

특정 문자열로 시작되거나 종료되는 record를 조회합니다. i가 붙으면 대소문자를 구별하지 않습니다.

  • in
>> Restaurant.objects.filter(id__in=[1,3]).values()

여러 값을 한번에 불러오는데, 위의 경우에는 id가 1인 record와 3인 record를 불러옵니다.

  • range
>> import datetime
>> start_date = datetime.datetime(2018,12,3,0,0,0)
>> end_date = datetime.datetime(2018,12,8,0,0,0)
>> Restaurant.objects.filter(created_at__range=(start_date, end_date)).values()

range는 범위 내의 해당하는 record를 불러옵니다.

3. 데이터 수정 및 삭제

3-1. 데이터 수정

데이터를 불러와서 수정 한 뒤, save를 호출해서 수정을 완료합니다.

>> item = Restaurant.objects.get(pk=1)
>> item.name 
‘Deli Shop’
>> item.name = ‘My Shop’
>> item.save() # save를 호출해야 실제로 저장됩니다.

UPDATE가 아닌 새로운 데이터를 INSERT하고 싶을 때는 다음과 같이 수행합니다.

>>> new_item = Restaurant() # 새로운 모델의 인스턴스를 생성
>>> new_item
<Restaurant: Restaurant object (None)>
>>> new_item.name = 'My Shop 2'

모델의 인스턴스에 primary값이 지정되어 있다면 save() 호출 시 UPDATE로 인식하고 UPDATE에 실패하면(해당 primary key에 레코드가 존재하지 않는 경우) INSERT합니다.

>>> new_item.address = 'Yeoksam'
>>> new_item.id = 1 # id를 지정 (primary key) 예전에 My Shop으로 이름을 지정한 레코드가 선택된다.
>>> new_item.created_at = datetime.datetime.now()
>>> new_item.updated_at = datetime.datetime.now()
>>> new_item.save() # update가 이루어 진다.

3-2. 데이터 삭제

delete() 메서드를 사용합니다.

>>> item.delete()
(1, {'third.Restaurant': 1})
profile
devzunky@gmail.com

1개의 댓글

comment-user-thumbnail
2022년 3월 20일

도움 많이 됐습니다. 좋은 글 감사합니다.

답글 달기