Django의 간단한 Model을 구현한 뒤에 DB에 데이터를 저장하고 저장한 데이터를 다루는 방법에 대해 포스팅하겠습니다.
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에서 데이터를 다뤄보겠습니다.
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를 생성해줍니다.
이제 조회해보겠습니다.
>> Restaurant.objects.all()
#Restaurant에 해당하는 데이터를 QuerySet의 형태로 모두 가져옵니다.
>> Restaurant.objects.all().values()
#values() 메서드를 사용해 실제 데이터에 들어있는 정보를 눈으로 확인할 수 있습니다.
정렬 순서를 변경할 수 있습니다.
>> Restaurant.objects.order_by('-created_at').values() # 최신순
>> Restaurant.objects.order_by('name').values() # 이름순
그냥 'created_at'으로 정렬하게 되면 작은 값부터 오름차순으로 정렬하게 되는데 그러면 가장 오래된 데이터부터 정렬됩니다.
-
를 붙이면 역순으로 정렬하게 됩니다.
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를 불러오는 것도 가능합니다.
하지만, 보통 데이터를 조회할 때는 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>)}]>
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>)}]>
데이터가 많은 경우, 페이지를 나눠서 조회합니다. 이를 paging혹은 pagination이라고 표현합니다.
>>> Restaurant.objects.all()[0:1] # start 0, end 1
record를 읽기 시작하는 위치, record를 읽을 마지막 값
slicing처럼 받아들이면 편합니다.
django orm의 field lookup을 사용해보겠습니다.
Restaurant.objects.filter(name=’Korean Food’)
위의 명령은 다음과 같습니다.
Restaurant.objects.filter(name__exact=’Korean Food’)
여태까지 __exact
를 사용한 것과 같은 것입니다.
이렇게 under score 2개와 조건을 붙이는 것이 field lookup입니다.
몇가지 조건 키워드들을 알아보겠습니다.
>> from third.models import Restaurant
>> Restaurant.objects.filter(name__contains=’Korea’).values()
>> 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를 뜻합니다.
>> Restaurant.objects.filter(name__startswith='Korea').values()
>> Restaurant.objects.filter(name__endswith='Food').values()
특정 문자열로 시작되거나 종료되는 record를 조회합니다. i가 붙으면 대소문자를 구별하지 않습니다.
>> Restaurant.objects.filter(id__in=[1,3]).values()
여러 값을 한번에 불러오는데, 위의 경우에는 id가 1인 record와 3인 record를 불러옵니다.
>> 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를 불러옵니다.
데이터를 불러와서 수정 한 뒤, 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가 이루어 진다.
delete() 메서드를 사용합니다.
>>> item.delete()
(1, {'third.Restaurant': 1})
도움 많이 됐습니다. 좋은 글 감사합니다.