장고 모델에서 모델 클래스를 정의하게 되면, 장고에서는 데이터를 추가/갱신하고 읽어드릴 수 있는 다양한 API들을 자동으로 제공합니다. 이런 기능들은 장고가 ORM 서비스를 제공에 따른 것으로 데이터베이스를 편리하게 핸들링 할 수 있게 도와줍니다.
- 장고는 디폴트로 모든 모델 클래스에 대해 "objects"라는 Manager (django.db.models.Manager) 객체를 자동으로 추가해서 사용할 수 있음.
- 이런 기능을 통해 우리는 데이터를 추가/삭제/조회 등을 할 수 있음.
- 장고 모델 매니저를 사용하기 위해서는 "모델클래스.objects"를 사용함.
- 객체명이 아니라 클래스명임을 주의 할 것
참고로, 장고에서 데이터를 조회/수정하는 것은 어드민에서도 할 수 있지만, 어드민에서의 사용은 크게 어렵지 않으므로 여기에서는 python manage.py shell
에서 진행하는 것을 정리하고자 합니다.
# create로 바로 생성하기
Poll.objects.create(question="점심 뭘 먹을까?", pub_date=datetime.now())
# 변수에 객체 담은 후 .save()로 저장
from blog.models import Blog
b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
b.save()
# 객체의 특정 속성 변경해서 저장할 경우,
b.name = 'New name'
b.save()
# create로 바로 생성하기
Entry.objects.create(blog_id=1, headline='head')
# 변수에 객체 담은 후 .save()로 저장
from blog.models import Blog, Entry
entry = Entry.objects.get(pk=1)
cheese_blog = Blog.objects.get(name="Cheddar Talk")
entry.blog = cheese_blog
entry.save()
ManyToManyField를 추가할 때는 add 메소드를 활용한다.
from blog.models import Author
joe = Author.objects.create(name="Joe")
entry.authors.add(joe)
(아래부터는 다른 사례임)
데이터 조회를 위해서는 아래와 같은 메소드를 이용할 수 있습니다.
- Poll.objects.all() : Poll 클래스의 모든 객체를 리스트로 리턴
- Poll.obejcts.values() : Poll 클래스 모든 객체의 데이터(딕셔너리 타입)를 리스트에 담아 리턴
- Poll.objects.filter(question="값") : Poll 클래스의 모든 객체 중 특정 조건이 맞는 객체를 리스트로 리턴 (필터 조건 복수일 수도 있으며, 복수의 객체 리턴 가능함)
- Poll.objects.get(id=1) : Poll 클래스 중 조건에 맞는 1개의 객체만 리턴함 (인자는 1개여야 함. 객체가 중복으로 리턴되는 것이면 에러 발생)
각각의 코드를 실행했을 때 확인할 수 있는 결과값은 아래와 같습니다.
이 때 주의해야 되는 점은 all(), filter()
의 리턴값은 객체가 담긴 리스트이고, get()은 객체라는 것입니다.
따라서 all(), filter()
의 리턴값을 변수에 담았다면, 객체의 데이터에 접근하기 위해서는 아래 이미지처럼 a[0].question
으로 객체에 먼저 접근한 뒤 해당객체의 프로퍼티를 불러와야 합니다. 반면, get()을 담은 변수는 그 자체가 이미 객체이기에 바로 프로퍼티를 불러와서 사용하면 됩니다.
이 외에 조회시 참고할 만한 메소드들은 아래와 같은 것들이 있습니다.
- Poll.objects.count() : 데이터(row 수) 수를 리턴
- Poll.objects.exclude(first_name='Kim') : 특정 조건 제외
- Poll.objects.order_by('id', -created) : 정렬 순서 id는 오름차순, created는 내림차순
- Poll.objects.first() : 데이터 중 첫번 째 row 리턴. 반대는 last()
- 위의 메소드들은 필요에 따라 복수로 사용가능함. 가령, 필터 후 어떤 값 순서로 세워서, 첫 번 째 값만 뽑는다 등
객체에 담긴 데이터를 수정할 때는 해당 객체를 변수에 담은 후 수정해서 저장하면 됩니다.
해당 row 객체에 접근해서 delete()
메소드로 삭제할 수 있습니다. 아래 이미지처럼 바로 삭제할 수도 있고, 변수에 담은 후 삭제할 수도 있습니다.
Field lookup은 특정한 조건을 충족하는 데이터만을 filter하여 보고 싶을 때 사용한다. filed__lookuptype=value
로 하여 사용할 수 있다.
사용할 수 있는 lookuptype으로는 exact, contains, startswith, endswith 등이 있다.
Entry.objects.filter(pub_date__lte='2006-01-01')
# SQL 쿼리문으로는 아래와 같음
SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01';
Entry.objects.get(headline__exact="Cat bites dog")
참조하고자 하는 object__fieldname
로 filtering할 수 있다. 역참조 관계를 참조할 경우에는 모델명의 lowercase를 object명으로 사용하면 된다.
# 정참조 관계인 Blog의 name 기준 필터링
Entry.objects.filter(blog__name='Beatles Blog')
# 역참조 관계인 Entry의 headline 기준 필터링
Blog.objects.filter(entry__headline__contains='Lennon')
# 여러 개 관계를 뛰어넘어 필터링
Blog.objects.filter(entry__authors__name='Lennon')
편의를 위해, 장고에서는 pk lookup shortcut을 제공한다.
아래 Blog 모델에서 primary key는 id필드이다. 따라서 아래 3가지 쿼리문은 모두 동일한 의미이다.
pk lookup은 맨 아래 예시처럼 조인문에서도 사용할 수 있다.
Blog.objects.get(id__exact=14) # Explicit form
Blog.objects.get(id=14) # __exact is implied
Blog.objects.get(pk=14) # pk implies id__exact
# Get blogs entries with id 1, 4 and 7
>>> Blog.objects.filter(pk__in=[1,4,7])
# Get all blog entries with id > 14
>>> Blog.objects.filter(pk__gt=14)
Entry.objects.filter(blog__id__exact=3) # Explicit form
>>> Entry.objects.filter(blog__id=3) # __exact is implied
>>> Entry.objects.filter(blog__pk=3) # __pk implies __id__exact