django QuerySet에 대해 공부한 점들을 기록합니다. 이 글은 engineertodeveloper과 django공식문서을 토대로 합니다.
Once you’ve created your data models, Django automatically gives you a database-abstraction API that lets you create, retrieve, update and delete objects. Django handles all the dirty work of communicating with the database for you.
django ORM을 이용하면, 어떤 데이터베이스이던 간에 같은 언어(파이썬)로 데이터베이스에 접근하고 데이터를 관리할 수 있다. django에서 모델을 만든이상, 데이터베이스에 일일이 SQL문을 던질 필요가 없다. 대신 django는 데이터베이스에 대한 API를 준다.
To represent database-table data in Python objects, Django uses an intuitive system: A model class represents a database table, and an instance of that class represents a particular record in the database table.
django는 직관적인 시스템을 쓴다. 모델 클래스는 DB의 테이블을 대표하고, 그 클래스의 인스턴스는 DB테이블의 특정한 데이터(record)를 대표한다.
from blog.models import Blog
b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
b.save()
This performs an INSERT
SQL statement behind the scenes. Django doesn’t hit the database until you explicitly call save().
To save changes to an object that’s already in the database, use save().
b5.name = 'New name'
b5.save()
This performs an UPDATE
SQL statement behind the scenes. Django doesn’t hit the database until you explicitly call save()
.
updated_at
속성에 자주 쓰이는 DateTimeField의 auto_now
는 save를 호출해야 적용되는 것 같다.
Updating a ForeignKey field works exactly the same way as saving a normal field – assign an object of the right type to the field in question.
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()
Updating a ManyToManyField works a little differently – use the add()
method on the field to add a record to the relation.
from blog.models import Author
joe = Author.objects.create(name="Joe")
entry.authors.add(joe)
A QuerySet represents a collection of objects from your database. It can have zero, one or many filters. Filters narrow down the query results based on the given parameters. In SQL terms, a QuerySet equates to a SELECT statement, and a filter is a limiting clause such as WHERE or LIMIT.
You get a QuerySet by using your model’s Manager. Each model has at least one Manager, and it’s called objects by default.
instance나 QuerySet은 그 자체로는 데이터를 나타낸다. 그러나 models.Model
로부터 상속받은 Manager를 이용한다면, QuerySet API, 즉 데이터베이스에 접근할 수 있게 된다. 매니저는 보통의 매니저(objects)와 참조매니저, 역참조매니저 등이 있다.
The Manager is the main source of QuerySets for a model. For example, Blog.objects.all() returns a QuerySet that contains all Blog objects in the database.
A Manager is the interface through which database query operations are provided to Django models. At least one Manager exists for every model in a Django application.
Manager은 모델에 대한 DB 쿼리문을 대신 실행해줄 인터페이스이다. 쉽게 말해서 DB에 대한 매니저다. 모든 모델은 최소한 한개의 매니저를 갖고 있다.
all
함수는 해당 모델클래스의 모든 인스턴스를, QuerySet에 담아서 반환한다.
filter
함수는 기본적으로는 all
과 같지만, 어떤 parameter에 대해 어떤 인자값을 받았느냐에 따라 다른 값을 필터링해서 반환한다.
exclude
함수는 filter과 정말 비슷하지만, 인자값에 해당하는 인스턴스들을 제외한 다른 모든 인스턴스들을 QuerySet에 담아서 반환한다.
__contains
: 특정column의 아이템이 특정 값을 포함하는 인스턴스만을 반환하도록 하고 싶다면, 모델에서 정의한 속성의 이름 뒤에 __contains
를 붙이면 된다.
__startswith
: 어떤 값으로 시작하냐를 필터링하고 싶다면.
__year
, __month
, __day
: DateTimeField의 경우, 특정 년 월 일을 필터링할 수 있다.
QuerySets are lazy – the act of creating a QuerySet doesn’t involve any database activity. You can stack filters together all day long, and Django won’t actually run the query until the QuerySet is evaluated.
q = Entry.objects.filter(headline__startswith="What")
q = q.filter(pub_date__lte=datetime.date.today())
q = q.exclude(body_text__icontains="food")
print(q)
Though this looks like three database hits, in fact it hits the database only once, at the last line (print(q)). In general, the results of a QuerySet aren’t fetched from the database until you “ask” for them. When you do, the QuerySet is evaluated by accessing the database.
Internally, a QuerySet can be constructed, filtered, sliced, and generally passed around without actually hitting the database. No database activity actually occurs until you do something to evaluate the queryset.
A QuerySet is iterable, and it executes its database query the first time you iterate over it. For example, this will print the headline of all entries in the database:
A view function, or view for short, is a Python function that takes a Web request and returns a Web response. This response can be the HTML contents of a Web page, or a redirect, or a 404 error, or an XML document, or an image . . . or anything, really. The view itself contains whatever arbitrary logic is necessary to return that response.
View는 클라이언트로부터 온 request를 받아서 response를 주기까지 필요한 로직을 말한다. 이 response는 웹페이지, redirect, 404에러, JSON, 이미지 등등이 될 수 있다. View는 무슨 로직을 갖고있든지 간에 response를 반환해야 한다.
사실 QuerySet API가 빠진 View는 DB없는 서버와 같다. View는 어떤 url에 대해서 실행할 함수일 뿐이다. 그러나 QuerySet API의 힘을 빌린다면 django서버에서 DB에 접근하고 정보 많은 사이트를 만들 수 있다.
django가 모델에 대해서 행하는 QuerySet API는 shell에서와 마찬가지로 View에서 쓸 수 있다. 예를 들어 회원가입에 대한 요청이 왔다고 할 때, django View에서는 요청에 담긴 (request.body) 데이터들을 토대로 DB에 접근, 수정, 생성을 할 수 있게 되는 것.