extra() 1
장고에서는 복잡한 WHERE 절을 표현하기가 쉽지 않은 경우가 있다. 이러한 경우에 extra() 를 사용하면 된다. 하지만 장고 문서 사이트에서는 QuerySet으로 표현이 안되는 최후의 경우에만 사용하는 것을 권고하는 것 같다.
정의에 의하면, extra lookups를 사용하면 다른 데이터베이스 엔진으로 변경될 때 SQL 코드가 명시적으로 작성된 것이 아니기 때문에 이동할 수 없을지도 모르고, DRH principle을 위반한다. 그래서 가능하면 extra() 사용을 피해야 한다. 2
params, select, where, tables 중에서 한개 이상을 사용할 수 있으며, default 값이 None으로 되어있기 때문에 적어도 한 개는 사용해야 한다.
select
Example 1:
Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
SELECT blog_entry.*, (pub_date > '2006-01-01') AS is_recent FROM blog_entry;
Example 2:
Blog.objects.extra( select={ 'entry_count': 'SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id' }, )
이 예제는 각 Blog 객체의 Entry 객체의 수를 subquery를 사용해서 entry_count라는 값으로 표현하고 있다.
결과를 SQL문으로 바꾸면 아래와 같다.
SELECT blog_blog.*, (SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id) AS entry_count FROM blog_blog;
장고의 select 절에서 subquery는 대부분 데이터베이스에서 지원하지 않으며, 몇 MySQL 버전과 같은 몇 데이터베이스는 subquery를 지원하지 않는다.
Example 3:
Blog.objects.extra( select=OrderedDict([('a', '%s'), ('b', '%s')]), select_params=('one', 'two'))
where / tables
주로 where는 non-explicit(implicit) join을 수행하는데 사용된다. tables를 사용하여 SQL에 여러 테이블을 추가할 수 있다.
where 와 tables는 모두 strings의 list로 작성할 수 있으며 모든 where parameters는 AND이다.
Example:
Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
위 django 코드를 SQL로 바뀌면 아래와 같다.
SELECT * FROM blog_entry WHERE (foo='a' OR bar='a') AND (baz='a')
쿼리에서 이미 tables를 사용했다면 tables parameters를 사용할 때는 조심해야 할 때 조심해야 한다. tables parameters를 사용하여 테이블을 추가할 때, 장고는 이미 테이블이 추가되었다고 가정한다.
order_by
extra를 사용하여 새로 추가한 컬럼이나 테이블을 사용하여 ordering 하고 싶을 때 사용된다. (테이블의 기본적인 ordering은 models.py에서 처리해야 한다.)
Example:
q = Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"}) q = q.extra(order_by = ['-is_recent'])
ordering 방법으로는 ascending이 기본이고, 컬럼명 앞에 -를 붙이면 descending 방식으로 ordering 된다.
params
Example:
Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
Bad:
Entry.objects.extra(where=["headline='Lennon'"])
Good:
Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
'Python > Django' 카테고리의 다른 글
[Django] uwsgi + nginx in ubuntu (0) | 2016.10.18 |
---|---|
[Django] Test (0) | 2016.10.12 |
[Django] Filter vs Exclude (0) | 2016.10.04 |
[Django] Custom Model Fields (0) | 2016.09.29 |
[Django] Abstract Model (0) | 2016.09.29 |
댓글