From a80f68e9b796dc7d0a00b63db18209fec2c827b3 Mon Sep 17 00:00:00 2001 From: Ho Sung Lee Date: Tue, 4 Sep 2018 00:53:47 +0900 Subject: [PATCH 001/100] first commit --- docs/index.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 0f9d3ff..54f5c97 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,11 +1,11 @@ -Django ORM Cookbook +장고 ORM 요리책 +++++++++++++++++++++++ -Django ORM Cookbook is a book about doing things with Django ORM and Django models. -Django is a “MTV” (Model-Template-View) framework – This book provides a deep dive into the :code:`M` part. +장고 ORM 요리책은 장고 ORM 과 장고의 models들를 사용하는 방법에 관한 책입니다. +장고는 "MTV" (모델-템플릿-뷰) 프레임워크입니다 - 이 책은 모델 파트에 대한 내용을 자세히 다룹니다. -They take the form of about 50 questions of the form :code:`How to do X with Django ORM/Queryset/Models`. +이 책은 장고 ORM/Queryset/Models의 사용법에 관한 50가지의 질문으로 구성되어 있습니다. .. image:: BookCover.jpg From aa31e262ba49ee673282c4b991080b140f09dab3 Mon Sep 17 00:00:00 2001 From: Ho Sung Lee Date: Tue, 4 Sep 2018 00:58:07 +0900 Subject: [PATCH 002/100] update index.rst --- docs/index.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 54f5c97..0dc9398 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -2,10 +2,10 @@ +++++++++++++++++++++++ -장고 ORM 요리책은 장고 ORM 과 장고의 models들를 사용하는 방법에 관한 책입니다. -장고는 "MTV" (모델-템플릿-뷰) 프레임워크입니다 - 이 책은 모델 파트에 대한 내용을 자세히 다룹니다. +장고 ORM 요리책은 장고 ORM 과 장고의 모델을 사용하는 방법에 관한 책입니다. +장고는 "MTV"(모델-템플릿-뷰) 프레임워크입니다 - 이 책은 모델 파트에 대한 내용을 자세히 다룹니다. -이 책은 장고 ORM/Queryset/Models의 사용법에 관한 50가지의 질문으로 구성되어 있습니다. +이 책은 장고 ORM/쿼리셋/모델의 사용법에 관한 50가지의 질문으로 구성되어 있습니다. .. image:: BookCover.jpg From 4e96357d7ee6fe0499ec5a3f2238d04525d8ce82 Mon Sep 17 00:00:00 2001 From: Lee Ho Sung Date: Tue, 4 Sep 2018 19:07:11 +0900 Subject: [PATCH 003/100] =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EB=AA=A9?= =?UTF-8?q?=EC=A0=81=EC=9C=BC=EB=A1=9C=20=EC=97=85=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 미안해요. --- docs/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index 0dc9398..c5398ee 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -14,7 +14,7 @@ introduction -Querying and Filtering +쿼리셋과 필터링 =============================================== .. toctree:: From f3738ab3dc138afe4d0398b84528af18d2148377 Mon Sep 17 00:00:00 2001 From: jungkwangyoun Date: Sat, 22 Sep 2018 15:46:48 +0900 Subject: [PATCH 004/100] =?UTF-8?q?order=5Fby=20=EB=B6=80=EB=B6=84=20?= =?UTF-8?q?=EB=B2=88=EC=97=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/order_by_annotated_field.rst | 6 +++--- docs/order_by_related_model.rst | 10 +++++----- docs/order_by_two.rst | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/order_by_annotated_field.rst b/docs/order_by_annotated_field.rst index db2a4cc..e7e1fce 100644 --- a/docs/order_by_annotated_field.rst +++ b/docs/order_by_annotated_field.rst @@ -1,7 +1,7 @@ -How to order on an annotated field? +주석처리된(annotated) 필드를 어떻게 정렬할 수 있을까? ========================================== -You have two models, :code:`Category` and :code:`Hero`. +여기 2개의 모델이 있습니다. :code:`Category` and :code: `Hero`. .. code-block:: python @@ -15,7 +15,7 @@ You have two models, :code:`Category` and :code:`Hero`. category = models.ForeignKey(Category, on_delete=models.CASCADE) -You want to get the :code:`Category`, ordered by number of :code:`Hero` in them. You can do this. +:code:`Hero`가 많은 순서대로 :code:`Category`를 얻고 싶다면 이렇게 하면 됩니다. .. code-block:: python diff --git a/docs/order_by_related_model.rst b/docs/order_by_related_model.rst index 42471d3..b269adc 100644 --- a/docs/order_by_related_model.rst +++ b/docs/order_by_related_model.rst @@ -1,8 +1,8 @@ -How to order on a field from a related model (with a foreign key)? +Foreign key로 연결된 모델의 필드로 정렬하려면 어떻게 해야할까? ======================================================================== -You have two models, :code:`Category` and :code:`Hero`. +여기 2개의 모델이 있습니다. :code:`Category`and :code:`Hero`. .. code-block:: python @@ -15,7 +15,7 @@ You have two models, :code:`Category` and :code:`Hero`. name = models.CharField(max_length=100) category = models.ForeignKey(Category, on_delete=models.CASCADE) -You want to order :code:`Hero` by category and inside each category by the :code:`Hero` name. You can do. +먼저는 category별로 정렬하고 그리고 각 category 내에서 `Hero`의 name순으로 정렬하려면 이렇게 할 수 있습니다. .. code-block:: python @@ -23,9 +23,9 @@ You want to order :code:`Hero` by category and inside each category by the :code 'category__name', 'name' ) -Note the double underscore(:code:`__` ) in :code:`'category__name'`. Using the double undertscore, you can order on a field from a related model. +:code:`'category__name'`에서 언더스코어 2개(:codeL`__`)를 유의하시기 바랍니다. 언더스코어 2개를 이용하면 관계가 있는 모델의 필드로 정렬을 할 수 있습니다. -If you look at the SQL. +이와 관련하여 아래 SQL로 나타낼 수 있습니다. .. code-block:: sql diff --git a/docs/order_by_two.rst b/docs/order_by_two.rst index 25d2ddb..0dae790 100644 --- a/docs/order_by_two.rst +++ b/docs/order_by_two.rst @@ -1,7 +1,7 @@ -How to order on two fields +어떻게 하면 2개의 필드를 기준으로 정렬할 수 있을까? ======================================================================== -:code:`order_by` on querysets can take one or more attribute names, allowing you to order on two or more fields. +쿼리셋에서 :code:`order_by`는 1개 내지는 그 이상의 필드로 정렬을 가능하게 해줍니다. ..code-block:: ipython From 0ca0b156974b036a9b8c481d8ec3e507a4a5426f Mon Sep 17 00:00:00 2001 From: jungkwangyoun Date: Sat, 22 Sep 2018 16:13:47 +0900 Subject: [PATCH 005/100] =?UTF-8?q?union=20=EB=B6=80=EB=B6=84=20=EB=B2=88?= =?UTF-8?q?=EC=97=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/union.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/union.rst b/docs/union.rst index bdb0e1f..6c4d924 100644 --- a/docs/union.rst +++ b/docs/union.rst @@ -1,10 +1,10 @@ -How to do union of two querysets from same or different models? +같은 모델 또는 다른 모델에서의 2개의 쿼리셋을 어떻게 합칠까(union)? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -The UNION operator is used to combine the result-set of two or more querysets. -The querysets can be from the same or from different models. When they querysets are from different models, the fields and their datatypes should match. +union은 2개 이상의 쿼리셋 결과물을 합칠 때 사용됩니다. +쿼리셋은 같거나 다른 모델에서 만들 수 있습니다. 만약 다른 모델을 통해 얻은 쿼리셋이라면, 필드와 데이터 타입을 맞춰야만 합니다. -Let's continue with our :code:`auth_user` model and generate 2 querysets to perform union operation +:code:`auth_user`을 통해 계속 보도록 합시다. 이 모델로부터 union을 하기 위해 2개의 쿼리셋을 생성하겠습니다. .. code-block:: python @@ -19,7 +19,7 @@ Let's continue with our :code:`auth_user` model and generate 2 querysets to perf >>> q2.union(q1) , , , , , , , , , ]> -Now try this +자, 해봅시다. .. code-block:: python @@ -30,10 +30,10 @@ Now try this django.db.utils.OperationalError: SELECTs to the left and right of UNION do not have the same number of result columns -The union operation can be performed only with the querysets having same fields and the datatypes. Hence our last union operation encountered error. You can do a union on two models as long as they have same fields or same subset of fields. +union은 오직 같은 필드와 같은 데이터타입을 갖는 쿼리셋으로 실행할 수 있습니다. 그렇기 때문에 위 마지막에 error를 만나게 된 겁니다. 같은 필드 쿼리셋이면 2개 모델에서 union을 실행할 수 있습니다. -Since :code:`Hero` and :code:`Villain` both have the :code:`name` and :code:`gender`, -we can use :code:`values_list` to limit the selected fields then do a union. +:code:`Hero`와 :code:`Villain` 두 개 모델 모두 :code:`name과 :code:`gender를 가지고 있기 때문에 +우리는 2개 필드로 제한하기 위해 :code:`values_list`를 사용한 후 union을 할 수 있습니다. .. code-block:: python @@ -45,4 +45,4 @@ we can use :code:`values_list` to limit the selected fields then do a union. "name", "gender" )) -This would give you all :code:`Hero` and :code:`Villain` objects with their name and gender. +위 코드를 통해 :code:`Hero`와 :code:`Villain` 모델의 name과 gender 모두를 얻게 될 것입니다. From 97cfcda0b6abf2a68cfbeba519985627d233248d Mon Sep 17 00:00:00 2001 From: anohk Date: Tue, 25 Sep 2018 15:47:28 +0900 Subject: [PATCH 006/100] ADD: 1.one_to_on TO 4.self-referencing --- docs/many_to_many.rst | 42 +++++++++++++++++++++--------------------- docs/one_to_many.rst | 11 ++++++----- docs/one_to_one.rst | 13 +++++++------ docs/self_fk.rst | 7 ++++--- 4 files changed, 38 insertions(+), 35 deletions(-) diff --git a/docs/many_to_many.rst b/docs/many_to_many.rst index 4fcacd1..07f2e21 100644 --- a/docs/many_to_many.rst +++ b/docs/many_to_many.rst @@ -1,13 +1,14 @@ -How to model many to many relationships? +다대다 관계는 어떻게 모델링하는가? =============================================== -A many-to-many relationship refers to a relationship between tables in a database when a parent row in one table contains several child rows in the second table, and vice versa. +다대다 관계는 하나의 레코드가 관계테이블의 여러 하위 레코드를 가질 수 있으며, 반대로도 가능합니다. -Just to make it more interactive, we will talk about a twitter app. By just using few fields and ManyToMany field we can make a simple twitter app. +인터렉티브한 것을 만들기 위해서, 트위터 앱에 관해 이야기 하려고 합니다. +우리는 몇 개의 필드와 ManyToMany 필드를 이용하여 간단한 트위터 앱을 만들 수 있습니다. +트위터에는 세 가지 기본적인 항목이 있습니다. 트윗, 팔로워, 마음에 들어요/마음에 들어요 취소 -We basically have 3 basic things in Twitter, tweets, followers, favourite/unfavourite. - -We have two models to make everything work. We are inheriting django's auth_user.:: +여기에 이 모든 것을 작동하게 하는 두 개의 모델이 있습니다. +우리는 여기서 Django의 auth_user를 상속할 것입니다. :: class User(AbstractUser): tweet = models.ManyToManyField(Tweet, blank=True) @@ -16,19 +17,18 @@ We have two models to make everything work. We are inheriting django's auth_user class Tweet(models.Model): tweet = models.TextField() - favourite = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, related_name='user_favourite') + favorite = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, related_name='user_favorite') def __unicode__(self): return self.tweet -What will the above model be able to do ? :: - - 1) User will able to follow/unfollow other users. - 2) User will able to see tweets made by other users whom user is following. - 3) User is able to favorite/unfavorite tweets. +위에 정의된 모델은 어떤 것이 가능할까요? :: + 1) 사용자는 다른 사용자를 팔로우/팔로우 취소를 할 수 있습니다. + 2) 사용자는 팔로잉하고 있는 사용자가 작성한 트윗을 볼 수 있습니다. + 3) 사용자는 트윗에 마음에 들어요/마음에 들어요 취소를 할 수 있습니다. -Few operations using ManyToManyfield which can be done are: :: +다대다 관계를 사용하여 수행할 수 있는 몇 가지 작업이 있습니다.: :: >>> t1 = Tweet(tweet="I am happy today") >>> t1.save() @@ -41,22 +41,22 @@ Few operations using ManyToManyfield which can be done are: :: >>> u3 = User(username='someuser', first_name='Some', last_name='User', email='some@example.com') >>> u3.save() -We have created few tweets and few users, that didn't involve any use of M2M field so far. Lets continue linking them in next step. :: +여기까지는 ManyToMany 필드의 어떤 용법도 사용하지 않은 채, 몇 개의 트윗과 사용자를 생성했습니다. 다음에는 이것들을 연결해봅시다. :: >>> u2.tweet.add(t1) >>> u2.save() >>> u2.tweet.add(t2) >>> u2.save() - // User can follow other users. + // 사용자는 다른 사용자를 팔로우할 수 있습니다. >>> u2.follow.add(u1) >>> u2.save() - // Tweets are linked to the users. Users have folloewd each other. Now we can make users do favourite/unfavourite of the tweets. - >>> t1.favourite.add(u1) + // 트윗은 사용자에게 연결되어 있습니다. 이제 사용자들이 트윗에 마음에 들어요/마음에 들어요 취소를 하게 할 수 있습니다. + >>> t1.favorite.add(u1) >>> t1.save() - >>> t1.favourite.add(u3) + >>> t1.favorite.add(u3) >>> t1.save() - // For removing any users vote - >>> t1.favourite.remove(u1) + // 사용자가 마음에 들어요 한 것을 취소하려면 + >>> t1.favorite.remove(u1) >>> t1.save() -Working example can be found in the repo: https://github.com/yashrastogi16/simpletwitter +작동하는 예제는 여기에서 볼 수 있습니다. : https://github.com/yashrastogi16/simpletwitter diff --git a/docs/one_to_many.rst b/docs/one_to_many.rst index 263d6f7..6a13691 100644 --- a/docs/one_to_many.rst +++ b/docs/one_to_many.rst @@ -1,8 +1,9 @@ -How to model one to many relationships? +일대다 관계는 어떻게 모델링하는가? =============================================== -In relational databases, a one-to-many relationship occurs when a parent record in one table can potentially reference several child records in another table. In a one-to-many relationship, the parent is not required to have child records; therefore, the one-to-many relationship allows zero child records, a single child record or multiple child records. -To define a many-to-one relationship, use `ForeignKey`.:: +관계형 데이터베이스에서는 한 테이블의 상위 레코드가 다른 테이블의 여러 하위 레코드를 참조할 수 있는 경우 일대다 관계가 발생합니다. +일대다 관계에서 상위 레코드가 하위 레코드를 필수적으로 가질 필요는 없습니다. 따라서 일대다 관계는 0개의 하위 레코드, 하나의 하위 레코드 또는 여러 개의 하위 레코드를 허용합니다. +일대다 관계를 정의하려면 ForeignKey를 사용하세요. :: class Article(models.Model): headline = models.CharField(max_length=100) @@ -27,7 +28,7 @@ To define a many-to-one relationship, use `ForeignKey`.:: >>> a1.reporter -If you try to assign an object before saving it you will encounter a ValueError :: +객체를 저장하기 전에 객체를 할당하려고 하면 ValueError가 발생합니다. :: >>> u3 = User(username='someuser', first_name='Some', last_name='User', email='some@example.com') >>> Article.objects.create(headline="This is a test", pub_date=date(2018, 3, 7), reporter=u1) @@ -38,4 +39,4 @@ If you try to assign an object before saving it you will encounter a ValueError >>> Article.objects.filter(reporter=u1) , ]> -The above queryset shows User u1 with multiple :code:`Articles`. Hence One to Many. +위의 쿼리셋은 u1의 여러 개의 :code:`Articles`를 보여줍니다. 따라서 일대다 관계임을 알 수 있습니다. diff --git a/docs/one_to_one.rst b/docs/one_to_one.rst index d33a16f..47a4034 100644 --- a/docs/one_to_one.rst +++ b/docs/one_to_one.rst @@ -1,9 +1,9 @@ -How to model one to one relationships? +일대일 관계는 어떻게 모델링하는가? =============================================== -One-to-one relationships occur when there is exactly one record in the first table that corresponds to one record in the related table. -Here we have an example where we know that each individual can have only one Biological parents i.e., Mother and Father. -We already have auth user model with us, we will add a new model UserParent as described below. :: +관계 테이블의 한 레코드에 상응하는 단 하나의 레코드가 있을때 일대일 관계가 발생합니다. +여기 우리가 잘 알고 있는 예시가 있습니다. 각 개인은 단 하나의 생물학적 부모 즉, 어머니와 아버지를 가질 수 있습니다. +우리는 사용자 인증 모델을 가지고 있으므로, 아래에 설명한 대로 새로운 UserParent 모델을 추가할 것입니다. :: from django.contrib.auth.models import User @@ -27,8 +27,9 @@ We already have auth user model with us, we will add a new model UserParent as d >>> p2.user.last_name 'Upadhyay' -The on_delete method is used to tell Django what to do with model instances that depend on the model instance you delete. (e.g. a ForeignKey relationship). The on_delete=models.CASCADE tells Django to cascade the deleting effect i.e. continue deleting the dependent models as well. :: +on_delete 메서드는 Django에 삭제하려는 모델 인스턴스에 의존하는 모델 인스턴스를 어떻게 처리해야 할지 지시합니다. (예: ForeignKey 관계) +on_delete=models.CASCADE는 계단식 삭제 즉, 종속모델까지 삭제하도록 Django에 지시합니다. :: >>> u2.delete() -Will also delete the related record of :code:`UserParent`. +이것은 :code:`UserParent` 의 관계 레코드까지 함께 삭제합니다. diff --git a/docs/self_fk.rst b/docs/self_fk.rst index 9018b9e..69ea569 100644 --- a/docs/self_fk.rst +++ b/docs/self_fk.rst @@ -1,9 +1,11 @@ How to include a self-referencing ForeignKey in a model +모델에 자기 참조 외래키를 어떻게 포함하는가? ======================================================================== -Self-referencing foreign keys are used to model nested relationships or recursive relationships. They work similar to how One to Many relationships. But as the name suggests, the model references itself. +자신을 참조하는 외래키는 중첩 또는 재귀 관계 모델에 사용합니다. +일대다 관계가 작동하는 것과 유사하지만 이름에서 알 수 있듯 모델은 자기 자신을 참조합니다. -Self reference Foreignkey can be achived in two ways. +자기 참조 외래키는 두 가지 방법으로 작성할 수 있습니다. .. code-block:: python @@ -15,4 +17,3 @@ Self reference Foreignkey can be achived in two ways. class Employee(models.Model): manager = models.ForeignKey("app.Employee", on_delete=models.CASCADE) - From dfd13d480b23aa31571f9dd09ff31d89187b9248 Mon Sep 17 00:00:00 2001 From: anohk Date: Tue, 25 Sep 2018 16:51:19 +0900 Subject: [PATCH 007/100] CHG: modify syntax --- docs/many_to_many.rst | 72 ++++++++++++++++++++++--------------------- docs/one_to_many.rst | 57 ++++++++++++++++++---------------- docs/one_to_one.rst | 36 ++++++++++++---------- docs/self_fk.rst | 5 ++- 4 files changed, 88 insertions(+), 82 deletions(-) diff --git a/docs/many_to_many.rst b/docs/many_to_many.rst index 07f2e21..f5a39f2 100644 --- a/docs/many_to_many.rst +++ b/docs/many_to_many.rst @@ -3,12 +3,13 @@ 다대다 관계는 하나의 레코드가 관계테이블의 여러 하위 레코드를 가질 수 있으며, 반대로도 가능합니다. -인터렉티브한 것을 만들기 위해서, 트위터 앱에 관해 이야기 하려고 합니다. -우리는 몇 개의 필드와 ManyToMany 필드를 이용하여 간단한 트위터 앱을 만들 수 있습니다. -트위터에는 세 가지 기본적인 항목이 있습니다. 트윗, 팔로워, 마음에 들어요/마음에 들어요 취소 +| 인터렉티브한 것을 만들기 위해서, 트위터 앱에 관해 이야기 하려고 합니다. +| 우리는 몇 개의 필드와 ManyToMany 필드를 이용하여 간단한 트위터 앱을 만들 수 있습니다. +| 트위터에는 트윗, 팔로워, 마음에 들어요/마음에 들어요 취소 와 같은 세 가지 기본적인 항목이 있습니다. -여기에 이 모든 것을 작동하게 하는 두 개의 모델이 있습니다. -우리는 여기서 Django의 auth_user를 상속할 것입니다. :: +여기에 이 모든 것이 작동하는 두 개의 모델이 있습니다. 우리는 여기서 Django의 auth_user를 상속할 것입니다. + +.. code-block :: python class User(AbstractUser): tweet = models.ManyToManyField(Tweet, blank=True) @@ -28,35 +29,36 @@ 2) 사용자는 팔로잉하고 있는 사용자가 작성한 트윗을 볼 수 있습니다. 3) 사용자는 트윗에 마음에 들어요/마음에 들어요 취소를 할 수 있습니다. -다대다 관계를 사용하여 수행할 수 있는 몇 가지 작업이 있습니다.: :: - - >>> t1 = Tweet(tweet="I am happy today") - >>> t1.save() - >>> t2 = Tweet(tweet="This is my second Tweet") - >>> t2.save() - >>> u1 = User(username='johny1', first_name='Johny', last_name='Smith', email='johny@example.com') - >>> u1.save() - >>> u2 = User(username='johny1', first_name='Johny', last_name='Smith', email='johny@example.com') - >>> u2.save() - >>> u3 = User(username='someuser', first_name='Some', last_name='User', email='some@example.com') - >>> u3.save() - -여기까지는 ManyToMany 필드의 어떤 용법도 사용하지 않은 채, 몇 개의 트윗과 사용자를 생성했습니다. 다음에는 이것들을 연결해봅시다. :: - - >>> u2.tweet.add(t1) - >>> u2.save() - >>> u2.tweet.add(t2) - >>> u2.save() - // 사용자는 다른 사용자를 팔로우할 수 있습니다. - >>> u2.follow.add(u1) - >>> u2.save() - // 트윗은 사용자에게 연결되어 있습니다. 이제 사용자들이 트윗에 마음에 들어요/마음에 들어요 취소를 하게 할 수 있습니다. - >>> t1.favorite.add(u1) - >>> t1.save() - >>> t1.favorite.add(u3) - >>> t1.save() - // 사용자가 마음에 들어요 한 것을 취소하려면 - >>> t1.favorite.remove(u1) - >>> t1.save() +다대다 관계를 사용하여 수행할 수 있는 몇 가지 작업이 있습니다. + +>>> t1 = Tweet(tweet="I am happy today") +>>> t1.save() +>>> t2 = Tweet(tweet="This is my second Tweet") +>>> t2.save() +>>> u1 = User(username='johny1', first_name='Johny', last_name='Smith', email='johny@example.com') +>>> u1.save() +>>> u2 = User(username='johny1', first_name='Johny', last_name='Smith', email='johny@example.com') +>>> u2.save() +>>> u3 = User(username='someuser', first_name='Some', last_name='User', email='some@example.com') +>>> u3.save() + +| 여기까지는 ManyToMany 필드의 어떤 용법도 사용하지 않은 채, 몇 개의 트윗과 사용자를 생성했습니다. +| 다음에는 이것들을 연결해봅시다. + +>>> u2.tweet.add(t1) +>>> u2.save() +>>> u2.tweet.add(t2) +>>> u2.save() +>>> # 사용자는 다른 사용자를 팔로우할 수 있습니다. +>>> u2.follow.add(u1) +>>> u2.save() +>>> # 트윗은 사용자에게 연결되어 있습니다. 이제 사용자들이 트윗에 마음에 들어요/마음에 들어요 취소를 하게 할 수 있습니다. +>>> t1.favorite.add(u1) +>>> t1.save() +>>> t1.favorite.add(u3) +>>> t1.save() +>>> # 사용자가 마음에 들어요 한 것을 취소하려면 +>>> t1.favorite.remove(u1) +>>> t1.save() 작동하는 예제는 여기에서 볼 수 있습니다. : https://github.com/yashrastogi16/simpletwitter diff --git a/docs/one_to_many.rst b/docs/one_to_many.rst index 6a13691..ac9b782 100644 --- a/docs/one_to_many.rst +++ b/docs/one_to_many.rst @@ -1,9 +1,12 @@ 일대다 관계는 어떻게 모델링하는가? =============================================== -관계형 데이터베이스에서는 한 테이블의 상위 레코드가 다른 테이블의 여러 하위 레코드를 참조할 수 있는 경우 일대다 관계가 발생합니다. -일대다 관계에서 상위 레코드가 하위 레코드를 필수적으로 가질 필요는 없습니다. 따라서 일대다 관계는 0개의 하위 레코드, 하나의 하위 레코드 또는 여러 개의 하위 레코드를 허용합니다. -일대다 관계를 정의하려면 ForeignKey를 사용하세요. :: +| 관계형 데이터베이스에서는 한 테이블의 상위 레코드가 다른 테이블의 여러 하위 레코드를 참조할 수 있는 경우 일대다 관계가 발생합니다. +| 일대다 관계에서 상위 레코드가 하위 레코드를 필수적으로 가질 필요는 없습니다. 따라서 일대다 관계는 0개의 하위 레코드, 하나의 하위 레코드 또는 여러 개의 하위 레코드를 허용합니다. + +일대다 관계를 정의하려면 ForeignKey를 사용하세요. + +.. code-block:: python class Article(models.Model): headline = models.CharField(max_length=100) @@ -16,27 +19,27 @@ class Meta: ordering = ('headline',) - >>> u1 = User(username='johny1', first_name='Johny', last_name='Smith', email='johny@example.com') - >>> u1.save() - >>> u2 = User(username='alien', first_name='Alien', last_name='Mars', email='alien@example.com') - >>> u2.save() - >>> from datetime import date - >>> a1 = Article(headline="This is a test", pub_date=date(2018, 3, 6), reporter=u1) - >>> a1.save() - >>> a1.reporter.id - 13 - >>> a1.reporter - - -객체를 저장하기 전에 객체를 할당하려고 하면 ValueError가 발생합니다. :: - - >>> u3 = User(username='someuser', first_name='Some', last_name='User', email='some@example.com') - >>> Article.objects.create(headline="This is a test", pub_date=date(2018, 3, 7), reporter=u1) - Traceback (most recent call last): - ... - ValueError: save() prohibited to prevent data loss due to unsaved related object 'reporter'. - >>> Article.objects.create(headline="This is a test", pub_date=date(2018, 3, 7), reporter=u1) - >>> Article.objects.filter(reporter=u1) - , ]> - -위의 쿼리셋은 u1의 여러 개의 :code:`Articles`를 보여줍니다. 따라서 일대다 관계임을 알 수 있습니다. +>>> u1 = User(username='johny1', first_name='Johny', last_name='Smith', email='johny@example.com') +>>> u1.save() +>>> u2 = User(username='alien', first_name='Alien', last_name='Mars', email='alien@example.com') +>>> u2.save() +>>> from datetime import date +>>> a1 = Article(headline="This is a test", pub_date=date(2018, 3, 6), reporter=u1) +>>> a1.save() +>>> a1.reporter.id +13 +>>> a1.reporter + + +객체를 저장하기 전에 객체를 할당하려고 하면 ValueError가 발생합니다. + +>>> u3 = User(username='someuser', first_name='Some', last_name='User', email='some@example.com') +>>> Article.objects.create(headline="This is a test", pub_date=date(2018, 3, 7), reporter=u1) +Traceback (most recent call last): +... +ValueError: save() prohibited to prevent data loss due to unsaved related object 'reporter'. +>>> Article.objects.create(headline="This is a test", pub_date=date(2018, 3, 7), reporter=u1) +>>> Article.objects.filter(reporter=u1) +, ]> + +위의 쿼리셋은 u1의 여러 개의 ``Articles`` 를 보여줍니다. 따라서 일대다 관계임을 알 수 있습니다. diff --git a/docs/one_to_one.rst b/docs/one_to_one.rst index 47a4034..cbcec67 100644 --- a/docs/one_to_one.rst +++ b/docs/one_to_one.rst @@ -1,9 +1,11 @@ 일대일 관계는 어떻게 모델링하는가? =============================================== -관계 테이블의 한 레코드에 상응하는 단 하나의 레코드가 있을때 일대일 관계가 발생합니다. -여기 우리가 잘 알고 있는 예시가 있습니다. 각 개인은 단 하나의 생물학적 부모 즉, 어머니와 아버지를 가질 수 있습니다. -우리는 사용자 인증 모델을 가지고 있으므로, 아래에 설명한 대로 새로운 UserParent 모델을 추가할 것입니다. :: +| 관계 테이블의 한 레코드에 상응하는 단 하나의 레코드가 있을때 일대일 관계가 발생합니다. +| 여기 우리가 잘 알고 있는 예시가 있습니다. 각 개인은 단 하나의 생물학적 부모 즉, 어머니와 아버지를 가질 수 있습니다. +| 우리는 사용자 인증 모델을 가지고 있으므로, 아래에 설명한 대로 새로운 UserParent 모델을 추가할 것입니다. + +.. code-block:: python from django.contrib.auth.models import User @@ -16,20 +18,20 @@ father_name = models.CharField(max_length=100) mother_name = models.CharField(max_length=100) - >>> u1 = User.objects.get(first_name='Ritesh', last_name='Deshmukh') - >>> u2 = User.objects.get(first_name='Sohan', last_name='Upadhyay') - >>> p1 = UserParent(user=u1, father_name='Vilasrao Deshmukh', mother_name='Vaishali Deshmukh') - >>> p1.save() - >>> p1.user.first_name - 'Ritesh' - >>> p2 = UserParent(user=u2, father_name='Mr R S Upadhyay', mother_name='Mrs S K Upadhyay') - >>> p2.save() - >>> p2.user.last_name - 'Upadhyay' +>>> u1 = User.objects.get(first_name='Ritesh', last_name='Deshmukh') +>>> u2 = User.objects.get(first_name='Sohan', last_name='Upadhyay') +>>> p1 = UserParent(user=u1, father_name='Vilasrao Deshmukh', mother_name='Vaishali Deshmukh') +>>> p1.save() +>>> p1.user.first_name +'Ritesh' +>>> p2 = UserParent(user=u2, father_name='Mr R S Upadhyay', mother_name='Mrs S K Upadhyay') +>>> p2.save() +>>> p2.user.last_name +'Upadhyay' -on_delete 메서드는 Django에 삭제하려는 모델 인스턴스에 의존하는 모델 인스턴스를 어떻게 처리해야 할지 지시합니다. (예: ForeignKey 관계) -on_delete=models.CASCADE는 계단식 삭제 즉, 종속모델까지 삭제하도록 Django에 지시합니다. :: +| on_delete 메서드는 Django에 삭제하려는 모델 인스턴스에 의존하는 모델 인스턴스를 어떻게 처리해야 할지 지시합니다. (예: ForeignKey 관계) +| on_delete=models.CASCADE는 계단식 삭제 즉, 종속모델까지 삭제하도록 Django에 지시합니다. - >>> u2.delete() +>>> u2.delete() -이것은 :code:`UserParent` 의 관계 레코드까지 함께 삭제합니다. +이것은 ``UserParent`` 의 관계 레코드까지 함께 삭제합니다. diff --git a/docs/self_fk.rst b/docs/self_fk.rst index 69ea569..72ea8c5 100644 --- a/docs/self_fk.rst +++ b/docs/self_fk.rst @@ -2,14 +2,13 @@ How to include a self-referencing ForeignKey in a model 모델에 자기 참조 외래키를 어떻게 포함하는가? ======================================================================== -자신을 참조하는 외래키는 중첩 또는 재귀 관계 모델에 사용합니다. -일대다 관계가 작동하는 것과 유사하지만 이름에서 알 수 있듯 모델은 자기 자신을 참조합니다. +| 자신을 참조하는 외래키는 중첩 또는 재귀 관계 모델에 사용합니다. +| 일대다 관계가 작동하는 것과 유사하지만 이름에서 알 수 있듯 모델은 자기 자신을 참조합니다. 자기 참조 외래키는 두 가지 방법으로 작성할 수 있습니다. .. code-block:: python - class Employee(models.Model): manager = models.ForeignKey('self', on_delete=models.CASCADE) From b62b207b6304ec76f78a01735cf43fa2d4a51da9 Mon Sep 17 00:00:00 2001 From: anohk Date: Tue, 25 Sep 2018 17:11:03 +0900 Subject: [PATCH 008/100] CHG: modify syntax --- docs/many_to_many.rst | 12 +++++++----- docs/one_to_many.rst | 4 ++-- docs/one_to_one.rst | 1 + docs/self_fk.rst | 4 ++-- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/docs/many_to_many.rst b/docs/many_to_many.rst index f5a39f2..3bbca11 100644 --- a/docs/many_to_many.rst +++ b/docs/many_to_many.rst @@ -1,13 +1,13 @@ 다대다 관계는 어떻게 모델링하는가? =============================================== -다대다 관계는 하나의 레코드가 관계테이블의 여러 하위 레코드를 가질 수 있으며, 반대로도 가능합니다. - +| 다대다 관계는 하나의 레코드가 관계테이블의 여러 하위 레코드를 가질 수 있으며, 반대로도 가능합니다. +| | 인터렉티브한 것을 만들기 위해서, 트위터 앱에 관해 이야기 하려고 합니다. | 우리는 몇 개의 필드와 ManyToMany 필드를 이용하여 간단한 트위터 앱을 만들 수 있습니다. | 트위터에는 트윗, 팔로워, 마음에 들어요/마음에 들어요 취소 와 같은 세 가지 기본적인 항목이 있습니다. - -여기에 이 모든 것이 작동하는 두 개의 모델이 있습니다. 우리는 여기서 Django의 auth_user를 상속할 것입니다. +| +| 여기에 이 모든 것이 작동하는 두 개의 모델이 있습니다. 우리는 여기서 Django의 auth_user를 상속할 것입니다. .. code-block :: python @@ -23,7 +23,9 @@ def __unicode__(self): return self.tweet -위에 정의된 모델은 어떤 것이 가능할까요? :: +위에 정의된 모델은 어떤 것이 가능할까요? + +:: 1) 사용자는 다른 사용자를 팔로우/팔로우 취소를 할 수 있습니다. 2) 사용자는 팔로잉하고 있는 사용자가 작성한 트윗을 볼 수 있습니다. diff --git a/docs/one_to_many.rst b/docs/one_to_many.rst index ac9b782..7ded570 100644 --- a/docs/one_to_many.rst +++ b/docs/one_to_many.rst @@ -3,8 +3,8 @@ | 관계형 데이터베이스에서는 한 테이블의 상위 레코드가 다른 테이블의 여러 하위 레코드를 참조할 수 있는 경우 일대다 관계가 발생합니다. | 일대다 관계에서 상위 레코드가 하위 레코드를 필수적으로 가질 필요는 없습니다. 따라서 일대다 관계는 0개의 하위 레코드, 하나의 하위 레코드 또는 여러 개의 하위 레코드를 허용합니다. - -일대다 관계를 정의하려면 ForeignKey를 사용하세요. +| +| 일대다 관계를 정의하려면 ForeignKey를 사용하세요. .. code-block:: python diff --git a/docs/one_to_one.rst b/docs/one_to_one.rst index cbcec67..67fce36 100644 --- a/docs/one_to_one.rst +++ b/docs/one_to_one.rst @@ -3,6 +3,7 @@ | 관계 테이블의 한 레코드에 상응하는 단 하나의 레코드가 있을때 일대일 관계가 발생합니다. | 여기 우리가 잘 알고 있는 예시가 있습니다. 각 개인은 단 하나의 생물학적 부모 즉, 어머니와 아버지를 가질 수 있습니다. +| | 우리는 사용자 인증 모델을 가지고 있으므로, 아래에 설명한 대로 새로운 UserParent 모델을 추가할 것입니다. .. code-block:: python diff --git a/docs/self_fk.rst b/docs/self_fk.rst index 72ea8c5..b3173eb 100644 --- a/docs/self_fk.rst +++ b/docs/self_fk.rst @@ -4,8 +4,8 @@ How to include a self-referencing ForeignKey in a model | 자신을 참조하는 외래키는 중첩 또는 재귀 관계 모델에 사용합니다. | 일대다 관계가 작동하는 것과 유사하지만 이름에서 알 수 있듯 모델은 자기 자신을 참조합니다. - -자기 참조 외래키는 두 가지 방법으로 작성할 수 있습니다. +| +| 자기 참조 외래키는 두 가지 방법으로 작성할 수 있습니다. .. code-block:: python From 2d818686b2248bbe37bc7b9726f544e60cc9b9ab Mon Sep 17 00:00:00 2001 From: anohk Date: Wed, 26 Sep 2018 16:46:27 +0900 Subject: [PATCH 009/100] =?UTF-8?q?ADD:=20=EB=B2=88=EC=97=AD=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/database_view.rst | 42 +++++++++++++++++++-------------- docs/existing_database.rst | 16 +++++++++---- docs/generic_models.rst | 48 +++++++++++++++++--------------------- 3 files changed, 58 insertions(+), 48 deletions(-) diff --git a/docs/database_view.rst b/docs/database_view.rst index 10423fe..49504d8 100644 --- a/docs/database_view.rst +++ b/docs/database_view.rst @@ -1,22 +1,30 @@ -How to add a model for a database view? +어떻게 데이터베이스 뷰에 모델을 추가하는가? =============================================== -A database view is a searchable object in a database that is defined by a query. Though a view doesn’t store data, some refer to a views as “virtual tables,” you can query a view like you can a table. A view can combine data from two or more table, using joins, and also just contain a subset of information. This makes them convenient to abstract, or hide, complicated queries. +| 데이터베이스 뷰는 쿼리로 정의된 데이터베이스에서 검색 가능한 객체입니다. +| 비록 뷰가 데이터를 저장하지는 않지만, 어떤 것들은 "가상 테이블"이라 불리며 테이블처럼 쿼리를 할 수 있습니다. +| 뷰는 조인을 사용해 둘 혹은 그 이상의 테이블에서 데이터를 조합할 수 있으며, 정보의 하위 부분만 포함합니다. +| 이로 인해 복잡한 쿼리를 쉽게 추상화하거나 은닉할 수 있습니다. -In our SqliteStuio we can see 26 tables and no views. +우리의 SqliteStuio에는 26개의 테이블을 볼 수 있고 뷰는 없습니다. .. image:: before_view.png -Lets create a simple view. :: +간단한 뷰를 만들어봅시다. - create view temp_user as - select id, first_name from auth_user; +.. code-block:: sql -After the view is created, we can see 26 tables and 1 view. + create view temp_user as + select id, first_name + from auth_user; + +뷰가 생성된 후, 우리는 26개의 테이블과 1개의 뷰를 확인할 수 있습니다. .. image:: after_view.png -We can create its related model in our app, by :code:`managed = False` and :code:`db_table="temp_user"` :: +앱에서 ``managed = False`` , ``db_table="temp_user"`` 로 관련 모델을 생성할 수 있습니다. + +.. code-block:: python class TempUser(models.Model): first_name = models.CharField(max_length=100) @@ -25,14 +33,14 @@ We can create its related model in our app, by :code:`managed = False` and :code managed = False db_table = "temp_user" - // We can query the newly created view similar to what we do for any table. - >>> TempUser.objects.all().values() - - // You cannot insert new reord in a view. - >>> TempUser.objects.create(first_name='Radhika', id=15) - Traceback (most recent call last): - ... - django.db.utils.OperationalError: cannot modify temp_user because it is a view +>>> # 테이블에 수행하는 것과 유사하게 새로 생성된 뷰에 쿼리를 할 수 있습니다. +>>> TempUser.objects.all().values() + +>>> # 뷰에 새로운 레코드를 삽입할 수는 없습니다. +>>> TempUser.objects.create(first_name='Radhika', id=15) +Traceback (most recent call last): +... +django.db.utils.OperationalError: cannot modify temp_user because it is a view -For view having union operation refer to : +union 연산이 있는 뷰는 다음을 참고하세요 : http://books.agiliq.com/projects/django-admin-cookbook/en/latest/database_view.html?highlight=view diff --git a/docs/existing_database.rst b/docs/existing_database.rst index 88ff10d..c164287 100644 --- a/docs/existing_database.rst +++ b/docs/existing_database.rst @@ -1,12 +1,20 @@ -How to convert existing databases to Django models? +이미 존재하는 데이터베이스를 어떻게 장고 모델로 변환하는가? ===================================================== -Django comes with a utility called :code:`inspectdb` that can create models by introspecting an existing database. You can view the output by running this command :: +| Django 에는 존재하는 데이터베이스를 검토하여 모델로 생성할 수 있는 ``inspectdb`` 라는 기능이 있습니다. +| 다음과 같은 명령어로 결과를 확인할 수 있습니다. + +:: $ python manage.py inspectdb -Befor running this you will have to configure your database in the :code:`settings.py` file. The result will be a file containing a model for each table. You may want to save that file :: +| 실행하기 전 반드시 ``settings.py`` 파일에 변환하려는 데이터베이스를 정의해야 합니다. +| 결과는 각 테이블의 모델을 담은 파일이 될 것입니다. + +다음과 같이 파일을 저장할 수 있습니다. + +:: $ python manage.py inspectdb > models.py -The output file will be saved to your current directory. Move that file to the correct app and you have a good starting point for further customizations. +위의 명령으로 결과 파일이 현재 디렉토리에 저장될 것입니다. 해당 파일을 앱의 올바른 위치로 이동시키면 추가적인 커스텀을 시작할 수 있게 됩니다. diff --git a/docs/generic_models.rst b/docs/generic_models.rst index 8703e5b..3e385c5 100644 --- a/docs/generic_models.rst +++ b/docs/generic_models.rst @@ -1,8 +1,7 @@ -How to create a generic model which can be related to any kind of entity? (Eg. a Category or a Comment?) +어떤 종류의 개체와도 연관 지을 수 있는 Generic 모델을 만드는 방법은? (예: 카테고리 또는 코멘트) ============================================================================================================= - -You have models like this. +다음과 같은 모델이 있습니다. .. code-block:: python @@ -26,9 +25,8 @@ You have models like this. # ... -:code:`Category` can be applied is a `generic` model. You prbably want to be able to apply categories to objects form any model class. -You can do it like this - +| ``Category`` 는 일반적인 모델입니다. 당신은 아마도 여러 모델 클래스 오브젝트에 카테고리를 적용하고 싶을 것입니다. +| 그렇다면 다음과 같이 할 수 있습니다. .. code-block:: python @@ -54,41 +52,37 @@ You can do it like this flex_category = GenericRelation(FlexCategory, related_query_name='flex_category') # ... +| ``FlexCategory`` 에 ``ForeignKey`` 와 ``PositiveIntegerField`` 를 사용하여 ``GenericForeignKey`` 필드를 적용했습니다. +| 그리고 카테고리를 적용하려는 모델에 ``GenericRelation`` 을 추가했습니다. +| +| 데이터베이스 레벨에서 보면 다음과 같습니다. -What did we do, we added we added a :code:`GenericForeignKey` fields on :code:`FlexCategory` using one :code:`ForeignKey` and one :code:`PositiveIntegerField`, then -added a :code:`GenericRelation` on the models you want to categorize. - - -At the database level it looks like this: - -.. code-block +================== ======================= ==================================================================== + Column Type Modifiers +================== ======================= ==================================================================== + id integer not null default nextval('entities_flexcategory_id_seq'::regclass) + name character varying(50) not null + object_id integer not null + content_type_id integer not null +================== ======================= ==================================================================== - Column | Type | Modifiers - -----------------+-----------------------+-------------------------------------------------------------------- - id | integer | not null default nextval('entities_flexcategory_id_seq'::regclass) - name | character varying(50) | not null - object_id | integer | not null - content_type_id | integer | not null - - -You can categorize a :code:`Hero` like this. +``Hero`` 는 다음과 같이 카테고리를 생성할 수 있습니다. .. code-block:: python - + hero = Hero.objects.create(name='Hades') FlexCategory.objects.create(content_object=hero, name="mythic") -And then get a :code:`Hero` categorised as 'ghost' like this +'ghost'로 분류된 ``Hero`` 는 다음과 같이 얻을 수 있습니다. .. code-block:: python - FlexCategory.objects.create(content_object=hero, name="ghost") + Hero.objects.filter(flex_category__name='ghost') -This gives us this sql. +위의 쿼리는 다음과 같은 sql을 만듭니다. .. code-block:: sql - SELECT "entities_hero"."name" FROM "entities_hero" INNER JOIN "entities_flexcategory" ON ("entities_hero"."id" = "entities_flexcategory"."object_id" From 7dfdeb578535c41a8120f894d29a277d2b3a144d Mon Sep 17 00:00:00 2001 From: anohk Date: Wed, 26 Sep 2018 17:20:56 +0900 Subject: [PATCH 010/100] modify syntax --- docs/existing_database.rst | 1 + docs/generic_models.rst | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/existing_database.rst b/docs/existing_database.rst index c164287..0f4b3ed 100644 --- a/docs/existing_database.rst +++ b/docs/existing_database.rst @@ -4,6 +4,7 @@ | Django 에는 존재하는 데이터베이스를 검토하여 모델로 생성할 수 있는 ``inspectdb`` 라는 기능이 있습니다. | 다음과 같은 명령어로 결과를 확인할 수 있습니다. + :: $ python manage.py inspectdb diff --git a/docs/generic_models.rst b/docs/generic_models.rst index 3e385c5..0feb227 100644 --- a/docs/generic_models.rst +++ b/docs/generic_models.rst @@ -1,4 +1,4 @@ -어떤 종류의 개체와도 연관 지을 수 있는 Generic 모델을 만드는 방법은? (예: 카테고리 또는 코멘트) +어떤 종류의 객체와도 연관 지을 수 있는 Generic 모델을 만드는 방법은? (예: 카테고리 또는 코멘트) ============================================================================================================= 다음과 같은 모델이 있습니다. @@ -28,6 +28,7 @@ | ``Category`` 는 일반적인 모델입니다. 당신은 아마도 여러 모델 클래스 오브젝트에 카테고리를 적용하고 싶을 것입니다. | 그렇다면 다음과 같이 할 수 있습니다. + .. code-block:: python from django.contrib.contenttypes.fields import GenericForeignKey @@ -57,6 +58,7 @@ | | 데이터베이스 레벨에서 보면 다음과 같습니다. + ================== ======================= ==================================================================== Column Type Modifiers ================== ======================= ==================================================================== @@ -68,8 +70,8 @@ ``Hero`` 는 다음과 같이 카테고리를 생성할 수 있습니다. - .. code-block:: python + hero = Hero.objects.create(name='Hades') FlexCategory.objects.create(content_object=hero, name="mythic") From 1a128ec2870d0d6f77081efdaef5338f908434e1 Mon Sep 17 00:00:00 2001 From: anohk Date: Wed, 26 Sep 2018 17:55:31 +0900 Subject: [PATCH 011/100] =?UTF-8?q?=EB=B2=88=EC=97=AD=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/keepdb.rst | 15 ++++++--------- docs/numqueries.rst | 20 +++++++++++--------- docs/refresh_from_db.rst | 25 ++++++++++++++----------- 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/docs/keepdb.rst b/docs/keepdb.rst index 65ec809..3894e11 100644 --- a/docs/keepdb.rst +++ b/docs/keepdb.rst @@ -1,15 +1,12 @@ -How to speed tests by reusing database between test runs? +테스트 실행을 할 때, 데이터베이스 재사용으로 테스트 속도를 높이는 방법은? ================================================================ -When we execute the command :code:`python manage.py test`, a new db is created everytime. This doesn't matter much if we don't have many migrations. - -But when we have many migrations, it takes a long time to recreate the database between the test runs. To avoid such situations, we may reuse the old database. - -You can prevent the test databases from being destroyed by adding the :code:`--keepdb` flag to the test command. This will preserve the test database between runs. If the database does not exist, it will first be created. If any migrations have been added since the last test run, -they will be applied in order to keep it up to date. - +| ``python manage.py test`` 명령을 실행할 때 마다 새로운 데이터베이스가 생성됩니다. 마이그레이션이 많지 않다면 이것은 그다지 문제가 되지 않습니다. +| 하지만 마이그레이션이 많은 경우, 테스트를 실행할 때 데이터베이스 재생성에 많은 시간을 소요하게 됩니다. 이런 상황을 피하기 위해서 이전에 생성된 데이터베이스를 사용할 수 있습니다. +| +| 테스트 명령에 ``--keepdb`` 플래그를 추가하면 데이터베이스가 삭제되는 것을 막고 테스트 실행 간 데이터베이스를 유지할 수 있습니다. +| 데이터베이스가 존재하지 않으면, 우선 데이터베이스를 생성합니다. 마지막 테스트 실행 이후 마이그레이션이 추가되면, 최신 상태를 유지하기 위해 이를 적용합니다. .. code-block:: bash $ python manage.py test --keepdb - diff --git a/docs/numqueries.rst b/docs/numqueries.rst index f8a3590..9915367 100644 --- a/docs/numqueries.rst +++ b/docs/numqueries.rst @@ -1,12 +1,14 @@ -How to assert that a function used a fixed number of queries? +함수가 고정된 개수의 쿼리를 실행하는지 확인하는 방법은? ======================================================================== -We can count number of queries for testing by using :code:`assertNumQueries()` method. :: +테스트에서 ``assertNumQueries()`` 메서드를 사용하면 쿼리의 개수를 확인할 수 있습니다. - def test_number_of_queries(self): - User.objects.create(username='testuser1', first_name='Test', last_name='user1') - # Above ORM create will run only one query. - self.assertNumQueries(1) - User.objects.filter(username='testuser').update(username='test1user') - # One more query added. - self.assertNumQueries(2) +.. code-block:: python + + def test_number_of_queries(self): + User.objects.create(username='testuser1', first_name='Test', last_name='user1') + # 위의 ORM은 하나의 쿼리를 실행할 것입니다. + self.assertNumQueries(1) + User.objects.filter(username='testuser').update(username='test1user') + # 쿼리가 하나 더 추가되었습니다. + self.assertNumQueries(2) diff --git a/docs/refresh_from_db.rst b/docs/refresh_from_db.rst index f39ae78..43af757 100644 --- a/docs/refresh_from_db.rst +++ b/docs/refresh_from_db.rst @@ -1,14 +1,17 @@ -How to reload a model object from the database? +데이터베이스에서 모델 객체를 다시 로드하는 방법은? ======================================================================== -Models can be reloaded from the databse using :code:`refresh_from_db()` method. THis proves helpful during testing. For example. :: +| ``refresh_from_db()`` 메서드를 사용하여 데이터베이스에서 모델을 다시 로드할 수 있습니다. +| 이것은 테스트에서 유용할 것입니다. 예를 들면, - class TestORM(TestCase): - def test_update_result(self): - userobject = User.objects.create(username='testuser', first_name='Test', last_name='user') - User.objects.filter(username='testuser').update(username='test1user') - # At this point userobject.val is still testuser, but the value in the database - # was updated to test1user. The object's updated value needs to be reloaded - # from the database. - userobject.refresh_from_db() - self.assertEqual(userobject.username, 'test1user') +.. code-block:: python + + class TestORM(TestCase): + def test_update_result(self): + userobject = User.objects.create(username='testuser', first_name='Test', last_name='user') + User.objects.filter(username='testuser').update(username='test1user') + # 여기에서 userobject의 이름은 여전히 'testuser'이지만, + # 데이터베이스에서는 'test1user'로 업데이트 되어있습니다. + # 속성이 업데이트 된 객체는 데이터베이스에서 다시 로드해야합니다. + userobject.refresh_from_db() + self.assertEqual(userobject.username, 'test1user') From be525e534005bff36c5c6d2bf37c984176ba3245 Mon Sep 17 00:00:00 2001 From: anohk Date: Wed, 26 Sep 2018 17:58:11 +0900 Subject: [PATCH 012/100] modify syntax --- docs/keepdb.rst | 2 +- docs/refresh_from_db.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/keepdb.rst b/docs/keepdb.rst index 3894e11..f174405 100644 --- a/docs/keepdb.rst +++ b/docs/keepdb.rst @@ -6,7 +6,7 @@ | | 테스트 명령에 ``--keepdb`` 플래그를 추가하면 데이터베이스가 삭제되는 것을 막고 테스트 실행 간 데이터베이스를 유지할 수 있습니다. | 데이터베이스가 존재하지 않으면, 우선 데이터베이스를 생성합니다. 마지막 테스트 실행 이후 마이그레이션이 추가되면, 최신 상태를 유지하기 위해 이를 적용합니다. - +| .. code-block:: bash $ python manage.py test --keepdb diff --git a/docs/refresh_from_db.rst b/docs/refresh_from_db.rst index 43af757..944d502 100644 --- a/docs/refresh_from_db.rst +++ b/docs/refresh_from_db.rst @@ -3,7 +3,7 @@ | ``refresh_from_db()`` 메서드를 사용하여 데이터베이스에서 모델을 다시 로드할 수 있습니다. | 이것은 테스트에서 유용할 것입니다. 예를 들면, - +| .. code-block:: python class TestORM(TestCase): From bd97ba13f3d02db5216acb99094535dbb9811f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=92=E1=85=A5=E1=84=8C=E1=85=A2=E1=84=8B=E1=85=A7?= =?UTF-8?q?=E1=86=BC?= Date: Wed, 26 Sep 2018 20:46:25 +0900 Subject: [PATCH 013/100] Translate Queryset ordering --- docs/asc_or_desc.rst | 14 +++++++------- docs/case_insensitive.rst | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/asc_or_desc.rst b/docs/asc_or_desc.rst index e861ee4..21705ab 100644 --- a/docs/asc_or_desc.rst +++ b/docs/asc_or_desc.rst @@ -1,23 +1,23 @@ -How to order a queryset in ascending or descending order? +쿼리셋을 어떻게 오름차순 혹은 내림차순으로 정렬할 수 있을까요? ============================================================= -Ordering of the queryset can be achieved by :code:`order_by` method. We need to pass the field on which we need to Order (ascending/descending) the result. -Query looks like this +쿼리셋은 :code:`order_by` 메서드를 사용해서 정렬할 수 있습니다. 오름차순 혹은 내림차순으로 정렬하기 위해선 기준이 되는 필드를 전달해야 합니다. +쿼리는 다음과 같습니다. .. code-block:: ipython - >>> User.objects.all().order_by('date_joined') # For ascending + >>> User.objects.all().order_by('date_joined') # 오름차순 , , , , , , , , , , , , ]> - >>> User.objects.all().order_by('-date_joined') # For descending; Not '-' sign in order_by method + >>> User.objects.all().order_by('-date_joined') # 내림차순 , , , , , , , , , , , , ]> -You can pass multiple fields to :code:`order_by` +여러개의 필드를 전달할 수도 있습니다. .. code-block:: ipython User.objects.all().order_by('date_joined', '-last_login') -Looking at the SQL +SQL은 다음과 같습니다. .. code-block:: sql diff --git a/docs/case_insensitive.rst b/docs/case_insensitive.rst index d28eb06..2652518 100644 --- a/docs/case_insensitive.rst +++ b/docs/case_insensitive.rst @@ -1,16 +1,16 @@ -How to order a queryset in case insensitive manner? +쿼리셋을 어떻게 대소문자 관계없이 정렬할 수 있을까요? ============================================================ .. image:: usertable2.png -Whenever we try to do :code:`order_by` with some string value, the ordering happens alphabetically and w.r.t case. Like +어떤 문자열들을 :code:`order_by` 를 통해 정렬하려고 할때, 정렬은 알파벳 순서 그리고 알파벳 대소문자를 구분합니다. 예를 들면 다음과 같습니다. .. code-block:: ipython >>> User.objects.all().order_by('username').values_list('username', flat=True) -If we want to order queryset in case insensitive manner, we can do like this . :: +만약 쿼리셋을 대소문자 구분 없이 문자열을 정렬하고 싶다면 다음과 같이 할 수 있습니다. .. code-block:: ipython @@ -18,10 +18,10 @@ If we want to order queryset in case insensitive manner, we can do like this . : >>> User.objects.all().order_by(Lower('username')).values_list('username', flat=True) -Alternatively, you can annotate with :code:`Lower` and then order on annotated field. +또 다른 방법으로는, :code:`Lower` 를 사용하여 Annotate된 필드를 생성하고, 해당 필드를 가지고 정렬 할 수 있습니다. .. code-block:: python User.objects.annotate( - uname=Lower('username') - ).order_by('uname').values_list('username', flat=True) + lower_name=Lower('username') + ).order_by('lower_name').values_list('username', flat=True) From ed47b2e29cfa98b25cce953cdc64cf31b96b94b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=92=E1=85=A5=E1=84=8C=E1=85=A2=E1=84=8B=E1=85=A7?= =?UTF-8?q?=E1=86=BC?= Date: Wed, 26 Sep 2018 20:58:36 +0900 Subject: [PATCH 014/100] Translate rest --- docs/order_by_annotated_field.rst | 8 +++----- docs/order_by_related_model.rst | 11 ++++++----- docs/order_by_two.rst | 5 ++--- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/docs/order_by_annotated_field.rst b/docs/order_by_annotated_field.rst index db2a4cc..ec44554 100644 --- a/docs/order_by_annotated_field.rst +++ b/docs/order_by_annotated_field.rst @@ -1,7 +1,7 @@ -How to order on an annotated field? +Annotate된 필드를 어떻게 정렬할 수 있을까요? ========================================== -You have two models, :code:`Category` and :code:`Hero`. +:code:`Category` 와 :code:`Hero` 모델이 있습니다. .. code-block:: python @@ -15,7 +15,7 @@ You have two models, :code:`Category` and :code:`Hero`. category = models.ForeignKey(Category, on_delete=models.CASCADE) -You want to get the :code:`Category`, ordered by number of :code:`Hero` in them. You can do this. +:code:`Category` 안에 속한 :code:`Hero` 의 숫자에 따라 정렬하고 싶다면, 다음과 같이 할 수 있습니다. .. code-block:: python @@ -24,5 +24,3 @@ You want to get the :code:`Category`, ordered by number of :code:`Hero` in them. ).order_by( "-hero_count" ) - - diff --git a/docs/order_by_related_model.rst b/docs/order_by_related_model.rst index 42471d3..898d88f 100644 --- a/docs/order_by_related_model.rst +++ b/docs/order_by_related_model.rst @@ -1,8 +1,8 @@ -How to order on a field from a related model (with a foreign key)? +어떻게 다른 테이블과 연결된 필드(외래키)를 기준으로 정렬할 수 있을까요? ======================================================================== -You have two models, :code:`Category` and :code:`Hero`. +:code:`Category` 와 :code:`Hero` 모델 두 개가 있습니다. .. code-block:: python @@ -15,7 +15,7 @@ You have two models, :code:`Category` and :code:`Hero`. name = models.CharField(max_length=100) category = models.ForeignKey(Category, on_delete=models.CASCADE) -You want to order :code:`Hero` by category and inside each category by the :code:`Hero` name. You can do. +:code:`Hero` 안에 있는 :code:`Hero` 의 이름을 통해 정렬하려면 다음과 같이 할 수 있습니다. .. code-block:: python @@ -23,9 +23,10 @@ You want to order :code:`Hero` by category and inside each category by the :code 'category__name', 'name' ) -Note the double underscore(:code:`__` ) in :code:`'category__name'`. Using the double undertscore, you can order on a field from a related model. +:code:`'category__name'`안에 있는 더블 언더스코어(:code:`__` )를 주의 깊게 살펴보세요. +더블 언더스코어를 사용하면, 연결된 모델의 필드를 기준으로 정렬할 수 있습니다. -If you look at the SQL. +SQL을 살펴보겠습니다. .. code-block:: sql diff --git a/docs/order_by_two.rst b/docs/order_by_two.rst index 25d2ddb..2c2a5f6 100644 --- a/docs/order_by_two.rst +++ b/docs/order_by_two.rst @@ -1,7 +1,7 @@ -How to order on two fields +어떻게 두 개의 필드를 정렬할까요? ======================================================================== -:code:`order_by` on querysets can take one or more attribute names, allowing you to order on two or more fields. +쿼리셋의 :code:`order_by` 메서드는 하나 이상의 필드의 이름을 가질 수 있습니다. 즉, 두 개 이상의 필드를 기준으로 정렬할 수 있습니다. ..code-block:: ipython @@ -9,4 +9,3 @@ How to order on two fields In [6]: User.objects.all().order_by("is_active", "-last_login", "first_name") Out[6]: , , ]> - From f684954749a11a1b7be91db4a2ed84815e598e91 Mon Sep 17 00:00:00 2001 From: hshwang-jdlab <35677719+hshwang-jdlab@users.noreply.github.com> Date: Wed, 26 Sep 2018 21:38:34 +0900 Subject: [PATCH 015/100] Update f_query.rst --- docs/f_query.rst | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/docs/f_query.rst b/docs/f_query.rst index fae9eca..ece0dae 100644 --- a/docs/f_query.rst +++ b/docs/f_query.rst @@ -1,12 +1,12 @@ -How to filter a queryset with criteria based on comparing their field values +필드 값 비교를 기준으로 쿼리셋 필터링 하기 ============================================================================== -Django ORM makes it easy to filter based on fixed values. -To get all :code:`User` objects with :code:`first_name` starting with :code:`'R'`, -you can do :code:`User.objects.filter(first_name__startswith='R')`. +Django ORM은 고정된 값으로 필터링하는 것을 도와줍니다. +:code:`first_name` 이 :code:`'R'` 로 시작하는 :code:`User` Object를 얻기 위해 +:code:`User.objects.filter(first_name__startswith='R')` 를 쓸 수 있습니다. +만약 first_name과 last_name을 비교하고 싶다면 :code:`F` obejct를 쓸 수 있습니다. +먼저 user를 만들어보겠습니다. -What if you want to compare the first_name and last name? -You can use the :code:`F` object. Create some users first. .. code-block:: ipython @@ -16,16 +16,16 @@ You can use the :code:`F` object. Create some users first. In [28]: User.objects.create_user(email="guido@example.com", username="Guido", first_name="Guido", last_name="Guido") Out[28]: -Now you can find the users where :code:`first_name==last_name` +이제 fisrt_name과 last_name이 같은 유저를 찾을 수 있습니다. + .. code-block:: ipython In [29]: User.objects.filter(last_name=F("first_name")) Out[29]: ]> -:code:`F` also works with calculated field using annotate. What if we wanted users whose first and last names have same letter? - -You can set the first letter from a string using :code:`Substr("first_name", 1, 1)`, so we do. +:code:`F` object는 annotate를 사용하여 계산된 필드에서도 사용할 수 있습니다. +만약 first_name과 last_name의 첫글자가 같은 유저를 찾길 원한다면 :code:`Substr("first_name", 1, 1)` 를 사용할 수 있습니다. .. code-block:: ipython @@ -35,4 +35,5 @@ You can set the first letter from a string using :code:`Substr("first_name", 1, In [46]: User.objects.annotate(first=Substr("first_name", 1, 1), last=Substr("last_name", 1, 1)).filter(first=F("last")) Out[46]: , ]> -:code:`F` can also be used with :code:`__gt`, :code:`__lt` and other expressions. +또한 :code:`F` object는 :code:`__gt`, :code:`__lt` 나 다른 expression과 함께 사용 가능합니다. + From 2b10a641c6a7f146967e4e3f6add91eed9628bac Mon Sep 17 00:00:00 2001 From: hshwang-jdlab <35677719+hshwang-jdlab@users.noreply.github.com> Date: Wed, 26 Sep 2018 21:43:14 +0900 Subject: [PATCH 016/100] Update filefield.rst --- docs/filefield.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/filefield.rst b/docs/filefield.rst index b73dc17..70dd31c 100644 --- a/docs/filefield.rst +++ b/docs/filefield.rst @@ -1,9 +1,7 @@ -How to filter FileField without any file? +어떻게 파일이 없는 Object를 FileField로 필터링 하나요? ++++++++++++++++++++++++++++++++++++++++++++++ -A :code:`FileField` or :code:`ImageField` stores the path of the file or image. At the DB level they are same as a :code:`CharField`. - -So to find FileField without any file we can query as under. +:code:`FileField` 나 :code:`ImageField` 는 파일이나 이미지의 경로를 저장합니다. Database 레벨에선 둘 모두 :code:`CharField` 로 같습니다. 아래의 쿼리로 파일이 없는 object를 찾을 수 있습니다. .. code-block:: python From 17439a0a87f34d274fd507e1114bfe3b92e53747 Mon Sep 17 00:00:00 2001 From: hshwang-jdlab <35677719+hshwang-jdlab@users.noreply.github.com> Date: Wed, 26 Sep 2018 21:44:10 +0900 Subject: [PATCH 017/100] Update join.rst --- docs/join.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/join.rst b/docs/join.rst index 5919d5c..c5b360c 100644 --- a/docs/join.rst +++ b/docs/join.rst @@ -1,7 +1,7 @@ -How to perform join operations in django ORM? +Django ORM에서 join 연산이 어떻게 작동하나요? ====================================================== -A SQL Join statement is used to combine data or rows from two or more tables based on a common field between them. Join can be carried out in many ways. Some are shown below. :: +SQL Join문은 둘 이상의 테이블 사이에서 공통 필드를 기반으로 데이터 혹은 행을 결합하는 데 사용됩니다. Join은 여러 방법으로 수행될 수 있으며 몇가지 예시는 아래와 같습니다. :: >>> a1 = Article.objects.select_related('reporter') // Using select_related >>> a1 @@ -12,4 +12,4 @@ A SQL Join statement is used to combine data or rows from two or more tables bas >>> a2 , , , , ]> >>> print(a2.query) - SELECT "events_article"."id", "events_article"."headline", "events_article"."pub_date", "events_article"."reporter_id", "events_article"."slug" FROM "events_article" INNER JOIN "auth_user" ON ("events_article"."reporter_id" = "auth_user"."id") WHERE "auth_user"."username" = John ORDER BY "events_article"."headline" ASC \ No newline at end of file + SELECT "events_article"."id", "events_article"."headline", "events_article"."pub_date", "events_article"."reporter_id", "events_article"."slug" FROM "events_article" INNER JOIN "auth_user" ON ("events_article"."reporter_id" = "auth_user"."id") WHERE "auth_user"."username" = John ORDER BY "events_article"."headline" ASC From 33b94e3499430a60fabb76233c4d359783c332e7 Mon Sep 17 00:00:00 2001 From: hshwang-jdlab <35677719+hshwang-jdlab@users.noreply.github.com> Date: Wed, 26 Sep 2018 21:47:36 +0900 Subject: [PATCH 018/100] Update second_largest.rst --- docs/second_largest.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/second_largest.rst b/docs/second_largest.rst index c97576e..5537c55 100644 --- a/docs/second_largest.rst +++ b/docs/second_largest.rst @@ -1,13 +1,12 @@ -How to find second largest record using Django ORM ? +어떻게 두번째로 큰 record를 찾을 수 있나요? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -You would across situations when you want to find second highest user depending on their age or salary. - -Though the ORM gives the flexibility of finding :code:`first()`, :code:`last()` item from the queryset but not nth item. You can do it using the slice operator. +연령이나 급여에 따라 두 번째로 높은 사용자를 찾고 싶은 경우가 있습니다. +Django ORM은 :code:`first()` 나 :code:`last()` 와 같은 방식으로 첫번째나 마지막 항목을 찾을 수 있는 유연성을 제공하지만 n번째 항목은 찾을 수 없습니다. 그럴때 slice 연산자를 사용하면 가능합니다 .. image:: usertable.png -We can find Nth records from the query by using slice operator. +slice 연산자를 사용하여 N번째 record를 찾을 수 있습니다. .. code-block:: python @@ -19,7 +18,8 @@ We can find Nth records from the query by using slice operator. 'Sohan' -:code:`User.objects.order_by('-last_login')[2]` only pulls up the required object from db using :code:`LIMIT ... OFFSET`. If you look at the generated sql, you would see something like this. +:code:`User.objects.order_by('-last_login')[2]` 해당 쿼리는 Database로 부터 세번째로 큰 결과만 가져오는 SQL구문을 생성합니다. +:code:`LIMIT ... OFFSET` 쿼리로 부터 생성된 SQL구문의 LIMIT ... OFFSET 부분을 확인할 수 있습니다. .. code-block:: sql From e9ff7d189ed90ac0a60bc2e59361f46a17f7c62d Mon Sep 17 00:00:00 2001 From: hshwang-jdlab <35677719+hshwang-jdlab@users.noreply.github.com> Date: Wed, 26 Sep 2018 21:50:42 +0900 Subject: [PATCH 019/100] Update distinct.rst --- docs/distinct.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/distinct.rst b/docs/distinct.rst index 7d339b1..61f0515 100644 --- a/docs/distinct.rst +++ b/docs/distinct.rst @@ -1,9 +1,10 @@ How to find distinct field values from queryset? +어떻게 쿼리셋에서 중복되지 않는 필드 값을 찾나요? ======================================================================== .. image:: usertable2.png -You want to find users whose names have not been repeated. You can do this like this +first_name이 중복되지 않는 유저를 찾기위해 아래와 같은 쿼리를 사용할 수 있습니다. .. code-block:: python @@ -14,6 +15,5 @@ You want to find users whose names have not been repeated. You can do this like ).filter(name_count=1) records = User.objects.filter(first_name__in=[item['first_name'] for item in distinct]) -This is different from :code:`User.objects.distinct("first_name").all()`, which will pull up the first record when it encounters a distinct :code:`first_name`. - +:code:`User.objects.distinct("first_name").all()`, 의 경우 중복된 :code:`first_name` 을 갖는 유저들 중 최초 유저를 가져오므로 위의 쿼리와 차이가 있습니다. From 60c9167cb9519969eb5d13e76050a757e7e860f7 Mon Sep 17 00:00:00 2001 From: hshwang-jdlab <35677719+hshwang-jdlab@users.noreply.github.com> Date: Wed, 26 Sep 2018 21:51:53 +0900 Subject: [PATCH 020/100] Update duplicate.rst --- docs/duplicate.rst | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/duplicate.rst b/docs/duplicate.rst index 30575c3..e28de1c 100644 --- a/docs/duplicate.rst +++ b/docs/duplicate.rst @@ -1,11 +1,9 @@ -Find rows which have duplicate field values +중복된 필드 값 갖는 열 찾기 ============================================== .. image:: usertable2.png -Say you want all users whose :code:`first_name` matches another user. - -You can find duplicate records using the technique below. +:code:`first_name` 이 일치하는 user들을 찾길 원한다고 가정해봅시다. 아래의 쿼리로 중복된 필드 값을 갖는 record들을 찾을 수 있습니다. .. code-block:: python @@ -15,7 +13,7 @@ You can find duplicate records using the technique below. >>> duplicates -If you need to fill all the records, you can do +위의 쿼리에 해당하는 모든 record들의 id를 찾기위해 아래와 같은 쿼리를 쓸 수 있습니다. .. code-block:: python From 824f9b0f993925c39592dd3a835a68638847d827 Mon Sep 17 00:00:00 2001 From: jungkwangyoun Date: Thu, 27 Sep 2018 11:01:34 +0900 Subject: [PATCH 021/100] =?UTF-8?q?annotated=20field=EC=97=90=20code=20blo?= =?UTF-8?q?ck=20=EA=B9=A8=EC=A7=84=20=EA=B1=B0=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/order_by_annotated_field.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/order_by_annotated_field.rst b/docs/order_by_annotated_field.rst index e7e1fce..e7e8d7d 100644 --- a/docs/order_by_annotated_field.rst +++ b/docs/order_by_annotated_field.rst @@ -1,7 +1,7 @@ 주석처리된(annotated) 필드를 어떻게 정렬할 수 있을까? ========================================== -여기 2개의 모델이 있습니다. :code:`Category` and :code: `Hero`. +여기 2개의 모델이 있습니다. :code:`Category` and :code:`Hero`. .. code-block:: python From 4e4b472ff3151ce91cabcf07a03c38c603ddffda Mon Sep 17 00:00:00 2001 From: jungkwangyoun Date: Thu, 27 Sep 2018 11:02:58 +0900 Subject: [PATCH 022/100] =?UTF-8?q?code=20block=20=EC=82=AC=EC=9D=B4?= =?UTF-8?q?=EC=97=90=20whitespace=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/order_by_annotated_field.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/order_by_annotated_field.rst b/docs/order_by_annotated_field.rst index e7e8d7d..1646318 100644 --- a/docs/order_by_annotated_field.rst +++ b/docs/order_by_annotated_field.rst @@ -1,7 +1,7 @@ 주석처리된(annotated) 필드를 어떻게 정렬할 수 있을까? ========================================== -여기 2개의 모델이 있습니다. :code:`Category` and :code:`Hero`. +여기 2개의 모델이 있습니다. :code:`Category` 와 :code:`Hero`. .. code-block:: python @@ -15,7 +15,7 @@ category = models.ForeignKey(Category, on_delete=models.CASCADE) -:code:`Hero`가 많은 순서대로 :code:`Category`를 얻고 싶다면 이렇게 하면 됩니다. +:code:`Hero` 가 많은 순서대로 :code:`Category` 를 얻고 싶다면 이렇게 하면 됩니다. .. code-block:: python From 6f0814cde9ab3be643193ee241cd1b13fe6cf8cf Mon Sep 17 00:00:00 2001 From: jungkwangyoun Date: Thu, 27 Sep 2018 11:04:48 +0900 Subject: [PATCH 023/100] =?UTF-8?q?code=20block=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/order_by_related_model.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/order_by_related_model.rst b/docs/order_by_related_model.rst index b269adc..a9d836d 100644 --- a/docs/order_by_related_model.rst +++ b/docs/order_by_related_model.rst @@ -2,7 +2,7 @@ Foreign key로 연결된 모델의 필드로 정렬하려면 어떻게 해야할 ======================================================================== -여기 2개의 모델이 있습니다. :code:`Category`and :code:`Hero`. +여기 2개의 모델이 있습니다. :code:`Category` 와 :code:`Hero`. .. code-block:: python @@ -15,7 +15,7 @@ Foreign key로 연결된 모델의 필드로 정렬하려면 어떻게 해야할 name = models.CharField(max_length=100) category = models.ForeignKey(Category, on_delete=models.CASCADE) -먼저는 category별로 정렬하고 그리고 각 category 내에서 `Hero`의 name순으로 정렬하려면 이렇게 할 수 있습니다. +먼저는 category별로 정렬하고 그리고 각 category 내에서 `Hero` 의 name순으로 정렬하려면 이렇게 할 수 있습니다. .. code-block:: python @@ -23,7 +23,7 @@ Foreign key로 연결된 모델의 필드로 정렬하려면 어떻게 해야할 'category__name', 'name' ) -:code:`'category__name'`에서 언더스코어 2개(:codeL`__`)를 유의하시기 바랍니다. 언더스코어 2개를 이용하면 관계가 있는 모델의 필드로 정렬을 할 수 있습니다. +:code:`'category__name'` 에서 언더스코어 2개( :code:`__` )를 유의하시기 바랍니다. 언더스코어 2개를 이용하면 관계가 있는 모델의 필드로 정렬을 할 수 있습니다. 이와 관련하여 아래 SQL로 나타낼 수 있습니다. From 7ca4e296b0061b8ab162b0c6b2756cc0ca5474fa Mon Sep 17 00:00:00 2001 From: jungkwangyoun Date: Thu, 27 Sep 2018 11:06:00 +0900 Subject: [PATCH 024/100] =?UTF-8?q?code=20block=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/order_by_two.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/order_by_two.rst b/docs/order_by_two.rst index 0dae790..b688b27 100644 --- a/docs/order_by_two.rst +++ b/docs/order_by_two.rst @@ -1,7 +1,7 @@ 어떻게 하면 2개의 필드를 기준으로 정렬할 수 있을까? ======================================================================== -쿼리셋에서 :code:`order_by`는 1개 내지는 그 이상의 필드로 정렬을 가능하게 해줍니다. +쿼리셋에서 :code:`order_by` 는 1개 내지는 그 이상의 필드로 정렬을 가능하게 해줍니다. ..code-block:: ipython From 38885dde6abb5f32430509c2040da88bbe050aa1 Mon Sep 17 00:00:00 2001 From: jungkwangyoun Date: Thu, 27 Sep 2018 11:07:54 +0900 Subject: [PATCH 025/100] =?UTF-8?q?code=20block=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/order_by_two.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/order_by_two.rst b/docs/order_by_two.rst index b688b27..de4e201 100644 --- a/docs/order_by_two.rst +++ b/docs/order_by_two.rst @@ -3,7 +3,7 @@ 쿼리셋에서 :code:`order_by` 는 1개 내지는 그 이상의 필드로 정렬을 가능하게 해줍니다. -..code-block:: ipython +.. code-block:: ipython In [5]: from django.contrib.auth.models import User From 752540971c732cbcfd3681bf064ce1e716d13d1a Mon Sep 17 00:00:00 2001 From: jungkwangyoun Date: Thu, 27 Sep 2018 11:14:05 +0900 Subject: [PATCH 026/100] =?UTF-8?q?code=20block=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/union.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/union.rst b/docs/union.rst index 6c4d924..726fa93 100644 --- a/docs/union.rst +++ b/docs/union.rst @@ -4,7 +4,7 @@ union은 2개 이상의 쿼리셋 결과물을 합칠 때 사용됩니다. 쿼리셋은 같거나 다른 모델에서 만들 수 있습니다. 만약 다른 모델을 통해 얻은 쿼리셋이라면, 필드와 데이터 타입을 맞춰야만 합니다. -:code:`auth_user`을 통해 계속 보도록 합시다. 이 모델로부터 union을 하기 위해 2개의 쿼리셋을 생성하겠습니다. +:code:`auth_user` 을 통해 계속 보도록 합시다. 이 모델로부터 union을 하기 위해 2개의 쿼리셋을 생성하겠습니다. .. code-block:: python @@ -32,8 +32,8 @@ union은 2개 이상의 쿼리셋 결과물을 합칠 때 사용됩니다. union은 오직 같은 필드와 같은 데이터타입을 갖는 쿼리셋으로 실행할 수 있습니다. 그렇기 때문에 위 마지막에 error를 만나게 된 겁니다. 같은 필드 쿼리셋이면 2개 모델에서 union을 실행할 수 있습니다. -:code:`Hero`와 :code:`Villain` 두 개 모델 모두 :code:`name과 :code:`gender를 가지고 있기 때문에 -우리는 2개 필드로 제한하기 위해 :code:`values_list`를 사용한 후 union을 할 수 있습니다. +:code:`Hero` 와 :code:`Villain` 두 개 모델 모두 :code:`name` 과 :code:`gender` 를 가지고 있기 때문에 +우리는 2개 필드로 제한하기 위해 :code:`values_list` 를 사용한 후 union을 할 수 있습니다. .. code-block:: python @@ -45,4 +45,4 @@ union은 오직 같은 필드와 같은 데이터타입을 갖는 쿼리셋으 "name", "gender" )) -위 코드를 통해 :code:`Hero`와 :code:`Villain` 모델의 name과 gender 모두를 얻게 될 것입니다. +위 코드를 통해 :code:`Hero` 와 :code:`Villain` 모델의 name과 gender 모두를 얻게 될 것입니다. From ad174b7cd194a44369b89fb30b6e765a012aa2a5 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sat, 29 Sep 2018 19:25:56 +0900 Subject: [PATCH 027/100] README, index --- README.md | 17 ++++++++--------- docs/index.rst | 26 +++++++++++++++----------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 63edae4..25b4222 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,17 @@ -### Django ORM cookbook +### 장고 ORM 요리책 -Django ORM cookbook is a set of recipes of how to do things with Django. -They take the form of about 50 questions of the form -`How to do X with Django ORM/Queryset`. +장고 ORM 요리책은 장고를 이용한 다양한 레시피(조리법)를 담은 책입니다. `장고 ORM/쿼리셋으로 ~을 하려면 어떻게 하나요?` 하는 50여 개의 질문과 답을 담고 있습니다. -We have a set of models which we use across the book for answering these questions. +이 책에서는 전체 주제 공통으로 아래에서 설명하는 데이터 모델을 이용합니다. -### The models -You plan to write a set of models and an assoicated admin for UMSRA researchers. You come up with two apps `entities` and `events`. The models are +### 모델 +여러분은 장고를 이용하여 UMSRA의 연구원들이 사용할 모델과 관리자 뷰(admin)를 제작하는 중입니다. 여러분은 프로젝트를 개체를 나타내는 `entities` 앱과 사건을 나타내는 `events` 앱 두 개로 나누어 작성하게 되었습니다. 그리고 각 앱의 모델을 다음과 같이 준비했습니다. (지금 자세히 보지 않아도 됩니다. 책을 보다가 필요하실 떄 참고해주세요.) -#### Events + +#### events 앱의 모델 from django.db import models @@ -86,7 +85,7 @@ You plan to write a set of models and an assoicated admin for UMSRA researchers. return self.a -#### Entities +#### Entities 앱의 모델 from django.db import models diff --git a/docs/index.rst b/docs/index.rst index c5398ee..5ebc2f0 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -2,10 +2,10 @@ +++++++++++++++++++++++ -장고 ORM 요리책은 장고 ORM 과 장고의 모델을 사용하는 방법에 관한 책입니다. -장고는 "MTV"(모델-템플릿-뷰) 프레임워크입니다 - 이 책은 모델 파트에 대한 내용을 자세히 다룹니다. +『장고 ORM 요리책(Django ORM Cookbook)』은 장고의 ORM과 모델을 이용한 다양한 레시피(조리법)를 담은 책입니다. 장고는 모델-템플릿-뷰(MTV) 프레임워크입니다. 이 책에서는 그 가운데 '모델'에 대해 상세히 다룹니다. + +이 책은 "장고 ORM/쿼리셋/모델으로 ~을 하는 방법은 무엇인가요?"와 같은 질문 50여 개와 그 답을 담고 있습니다. -이 책은 장고 ORM/쿼리셋/모델의 사용법에 관한 50가지의 질문으로 구성되어 있습니다. .. image:: BookCover.jpg @@ -14,8 +14,9 @@ introduction -쿼리셋과 필터링 -=============================================== + +정보를 질의하고 걸러내기 +======================== .. toctree:: :maxdepth: 1 @@ -40,8 +41,8 @@ func_expressions -Creating, Updating and Deleting things -=============================================== +정보를 생성/갱신/삭제하기 +======================= .. toctree:: :maxdepth: 1 @@ -56,7 +57,7 @@ Creating, Updating and Deleting things datetime -Ordering things +질의 결과를 정렬하기 ======================== .. toctree:: @@ -70,7 +71,7 @@ Ordering things order_by_annotated_field -Database Modelling +데이터베이스 모델 짜기 ============================================== .. toctree:: @@ -94,7 +95,7 @@ Database Modelling -Testing +테스트하기 =============================================== .. toctree:: :maxdepth: 1 @@ -104,9 +105,12 @@ Testing keepdb refresh_from_db -Indices and tables + + +찾아보기 / 표 ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` + From 6930675b1889d81967122496b66eae63a39d7b30 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sat, 29 Sep 2018 19:52:41 +0900 Subject: [PATCH 028/100] introduction --- docs/introduction.rst | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/docs/introduction.rst b/docs/introduction.rst index 0296691..0a469be 100644 --- a/docs/introduction.rst +++ b/docs/introduction.rst @@ -1,18 +1,17 @@ -Introduction +개요 ----------------- -Django ORM is one of the key pillars of Django. It provides abstractions to work with databases, in a mostly database agnostic way. +장고 ORM은 장고의 핵심 구성요소 가운데 하나로, 우리가 데이터베이스 시스템을 직접 다루지 않고도 데이터베이스를 활용할 수 있도록 편리하고도 강력한 인터페이스를 제공합니다. 장고 ORM은 "간단한 것을 쉽게, 어려운 것도 할 수 있게" 해 줍니다. -Django ORM combines ease of use with powerful abstractions. It keeps "Simple things easy and hard things possible". +이 책은 여러 가지 예제로 문제 상황을 직접 다뤄보며 장고 ORM을 익히도록 합니다. 여러분의 장고 ORM의 이해도를 높여 줄 50여 개의 질문을 준비했습니다. -In this book, we will learn Django ORM by doing things with it. We will ask about 50 questions about Django ORM, and get a deeper understanding of the ORM. - -How to read this book. +이 책을 읽는 방법 +++++++++++++++++++++++++ -Each chapter in the book is question. The questions are grouped in related chapters. You can read the book in eaither of two ways. +이 책의 각 장은 각각 질문 하나를 나타냅니다. 비슷한 주제를 다루는 질문들은 서로 모아 두었습니다. 이 책을 읽는 방법은 크게 두 가지가 있습니다. + +1. 특정한 질문에 관한 답을 찾는다면 그 질문을 다루는 장과 그와 연결된 장을 함께 읽으세요. +2. 장고 ORM와 모델 계층에 대한 이해도를 높이고 싶다면 책을 처음부터 차례대로 읽으세요. -1. If you are looking to get answers to specific questions, read that chapter and other chapters in that group. -2. If you are need to get a deeper understanding of Django ORM and models layer, read the chapters from start to the end. From 13adc119a9dc37cf8ce53d7e2e1aea3881b5e0ed Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sat, 29 Sep 2018 20:23:35 +0900 Subject: [PATCH 029/100] query --- docs/query.rst | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/query.rst b/docs/query.rst index 7a2e3f9..58ee7b8 100644 --- a/docs/query.rst +++ b/docs/query.rst @@ -1,10 +1,9 @@ -How to find the query associated with a queryset? -++++++++++++++++++++++++++++++++++++++++++++++++++ +쿼리셋에 의해 실행되는 SQL 질의문을 확인하고 싶어요 +++++++++++++++++++++++++++++++++++++++++++++++ -Sometime you want to know how a Django ORM makes our queries execute or what is the corresponding SQL of the code you are writing. This is very strightforward. Youn can get :code:`str` of any :code:`queryset.query` to get the sql. +장고 ORM이 실행하는 질의문 또는 우리가 작성한 코드에 대응하는 SQL 질의문이 무엇인지 확인하고 싶을 때가 있습니다. 확인하는 방법은 매우 직관적인데요, SQL 질의문을 구하고 싶은 :code:`queryset.query`의 :code:`str`을 확인하면 됩니다. -You have a model called :code:`Event`. For getting all records, you will write something like -:code:`Event.objects.all()`, then do :code:`str(queryset.query)` +:code:`Event`라는 모델이 있을 때, 이 모델의 모든 행을 데이터베이스에서 읽어오려면 :code:`Event.objects.all()`과 같은 코드를 작성하면 됩니다. 이렇게 구한 쿼리셋의 :code:`str(queryset.query)`를 확인하여 SQL 질의문을 살펴봅시다. .. code-block:: python @@ -16,7 +15,7 @@ You have a model called :code:`Event`. For getting all records, you will write s .. image:: sql_query.png -Example 2 +두 번째 예제 .. code-block:: python From 7ec7618405e19ddfadad9858a1bb95ed16394ffe Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sat, 29 Sep 2018 20:34:21 +0900 Subject: [PATCH 030/100] or_query --- docs/or_query.rst | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/docs/or_query.rst b/docs/or_query.rst index fb6f47e..a6d682c 100644 --- a/docs/or_query.rst +++ b/docs/or_query.rst @@ -1,27 +1,28 @@ -How to do OR queries in Django ORM? -++++++++++++++++++++++++++++++++++++++++++++++++++ +여러 조건을 OR 연산하여 데이터를 걸러내려면 어떻게 하나요? +++++++++++++++++++++++++++++++++++++++++++++++++++++ .. image:: usertable.png -If you are using :code:`django.contrib.auth`, you will have a table called :code:`auth_user`. It will have fields as :code:`username`, :code:`first_name`, :code:`last_name` and more. +장고의 사용자 계정 관리 앱인 :code:`django.contrib.auth`를 사용하면 데이터베이스에 :code:`auth_user`이라는 표가 생성됩니다. 이 표에는 :code:`username`, :code:`first_name`, :code:`last_name` 등의 열이 있습니다. -A common requirement is performing :code:`OR` filtering with two ore more conditions. Say you want find all users with firstname starting with 'R' and last_name starting with 'D'. +데이터를 걸러낼 때, 두 가지 이상의 조건을 :code:`OR` 연산하여야 하는 경우가 많습니다. 이름이 'R'로 시작하거나 성이 'D'로 시작하는 모든 사용자를 구한다고 해 봅시다. -Django provides two options. +장고에서는 다음 두 방법으로 구할 수 있습니다. - :code:`queryset_1 | queryset_2` - :code:`filter(Q()|Q()` -The query in detail + +질의문 살펴보기 ----------------------- -The SQL query for the above condition will look something like :: +위 조건의 SQL 질의문은 대략 다음과 같습니다. :: SELECT username, first_name, last_name, email FROM auth_user WHERE first_name LIKE 'R%' OR last_name LIKE 'D%'; .. image:: sqluser_result1.png -Similarly our ORM query would look like +장고 ORM 코드도 비슷합니다. .. code-block:: python @@ -33,7 +34,7 @@ Similarly our ORM query would look like queryset , , , , ]> -You can also look at the generated query. +장고 ORM이 생성하는 SQL 질의문도 한 번 확인해 봅시다. .. code-block:: python @@ -44,14 +45,14 @@ You can also look at the generated query. "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE ("auth_user"."first_name"::text LIKE R% OR "auth_user"."last_name"::text LIKE D%)' -Alternatively, you can use the :code:`Q` objects. +:code:`Q` 객체를 이용하는 방법도 가능합니다. .. code-block:: python from django.db.models import Q qs = User.objects.filter(Q(first_name__startswith='R')|Q(last_name__startswith='D')) -If you look at the generated query, the result is exactly the same +두 방법 모두 생성되는 SQL 질의문은 완전히 동일합니다. .. code-block:: ipython From c73efa387fd987ebfc1c1d8e7e0f9df02d2f391e Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sat, 29 Sep 2018 21:00:26 +0900 Subject: [PATCH 031/100] and_Query --- docs/and_query.rst | 26 +++++++++++--------------- docs/or_query.rst | 6 +++--- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/docs/and_query.rst b/docs/and_query.rst index f597b50..4e7bf8d 100644 --- a/docs/and_query.rst +++ b/docs/and_query.rst @@ -1,27 +1,23 @@ -How to do AND queries in Django ORM? -++++++++++++++++++++++++++++++++++++++++++++++++++ +AND 연산으로 여러 조건을 모두 만족하는 행을 구하려면 어떻게 하나요? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .. image:: usertable.png -If you are using :code:`django.contrib.auth`, you will have a table called :code:`auth_user`. It will have fields as :code:`username`, :code:`first_name`, :code:`last_name` and more. +장고의 사용자 계정 관리 앱인 :code:`django.contrib.auth`를 사용하면 데이터베이스에 :code:`auth_user`이라는 표가 생성됩니다. 이 표에는 :code:`username`, :code:`first_name`, :code:`last_name` 등의 열이 있습니다. +:code:`AND` 연산으로 여러 조건을 모두 만족하는 행을 구해야 하는 경우가 많습니다. 이름이 'R'로 시작하고 성이 'D'로 시작하는 모든 사용자를 구한다고 해 봅시다. -You would frequently need to want to perform AND operation, to find querysets which match multiple criteria. - -Say you want to find users with :code:`firstname` starting with 'R' AND :code:`last_name` starting with 'D'. - -Django provides three options. +장고에서는 다음 세 방법으로 구할 수 있습니다. - :code:`filter(, )` - :code:`queryset_1 & queryset_2` - :code:`filter(Q() & Q())` -The query in detail +질의문 살펴보기 ----------------------- - -Our SQL query for the above condition will look something like +위 조건의 SQL 질의문은 다음과 같은 형태입니다. .. code-block:: sql @@ -29,7 +25,7 @@ Our SQL query for the above condition will look something like .. image:: sqluser_result2.png -The default way to combine multiple conditions in :code:`filter` is :code:`AND`, so you can just do. +장고 쿼리셋의 :code:`filter` 메서드에서 여러 조건을 결합하는 방법은 기본적으로 :code:`AND` 방식입니다. 따라서 다음과 같이 조건을 그냥 나열하면 됩니다. .. code-block:: python @@ -38,7 +34,7 @@ The default way to combine multiple conditions in :code:`filter` is :code:`AND`, last_name__startswith='D' ) -Alternatively, you can explicitly use the `&` operator on querysets. +하지만 `&` 연산자를 사용하여 쿼리셋을 명시적으로 결합할 수도 있습니다. .. code-block:: python @@ -48,7 +44,7 @@ Alternatively, you can explicitly use the `&` operator on querysets. last_name__startswith='D' ) -For complete customisability, you can use the :code:`Q` objects. +복잡한 질의를 수행할 수 있도록 도와주는 :code:`Q` 객체를 이용하여 조건을 명시해도 됩니다. .. code-block:: python @@ -61,7 +57,7 @@ For complete customisability, you can use the :code:`Q` objects. queryset_1 , , ]> -You can look at the generated query and verify that they are all same. +언제나 실제로 생성되는 SQL 질의문을 확인하여 검증하는 것이 도움이 됩니다. .. code-block:: ipython diff --git a/docs/or_query.rst b/docs/or_query.rst index a6d682c..149df59 100644 --- a/docs/or_query.rst +++ b/docs/or_query.rst @@ -1,11 +1,11 @@ -여러 조건을 OR 연산하여 데이터를 걸러내려면 어떻게 하나요? -++++++++++++++++++++++++++++++++++++++++++++++++++++ +OR 연산으로 일부 조건을 하나라도 만족하는 행을 구하려면 어떻게 하나요? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .. image:: usertable.png 장고의 사용자 계정 관리 앱인 :code:`django.contrib.auth`를 사용하면 데이터베이스에 :code:`auth_user`이라는 표가 생성됩니다. 이 표에는 :code:`username`, :code:`first_name`, :code:`last_name` 등의 열이 있습니다. -데이터를 걸러낼 때, 두 가지 이상의 조건을 :code:`OR` 연산하여야 하는 경우가 많습니다. 이름이 'R'로 시작하거나 성이 'D'로 시작하는 모든 사용자를 구한다고 해 봅시다. +:code:`OR` 연산으로 여러 조건 중 하나라도 만족하는 행을 구해야 하는 경우가 많습니다. 이름이 'R'로 시작하거나 성이 'D'로 시작하는 모든 사용자를 구한다고 해 봅시다. 장고에서는 다음 두 방법으로 구할 수 있습니다. From afbdf39725a6bb10a4943b0f27c84f028d6dae18 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sat, 29 Sep 2018 21:04:12 +0900 Subject: [PATCH 032/100] notequal_query --- docs/notequal_query.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/notequal_query.rst b/docs/notequal_query.rst index 444d8ba..55b3784 100644 --- a/docs/notequal_query.rst +++ b/docs/notequal_query.rst @@ -1,28 +1,28 @@ -How to do a NOT query in Django queryset? +NOT 연산으로 조건을 부정하려면 어떻게 하나요? ++++++++++++++++++++++++++++++++++++++++++++++++++ .. image:: usertable.png -If you are using :code:`django.contrib.auth`, you will have a table called :code:`auth_user`. It will have fields as :code:`username`, :code:`first_name`, :code:`last_name` and more. +장고의 사용자 계정 관리 앱인 :code:`django.contrib.auth`를 사용하면 데이터베이스에 :code:`auth_user`이라는 표가 생성됩니다. 이 표에는 :code:`username`, :code:`first_name`, :code:`last_name` 등의 열이 있습니다. -Say you want to fetch all users with id NOT < 5. You need a NOT operation. +id < 5 라는 조건을 만족하지 않는 모든 사용자를 구하려 한다고 해 봅시다. 이를 수행하려면 NOT 연산이 필요합니다. -Django provides two options. +장고에서는 다음 두 방법으로 구할 수 있습니다. - :code:`exclude()` - :code:`filter(~Q())` -The query in detail ------------------------ +질의문 살펴보기 +----------------------- -Our SQL query for the above condition will look something like :: +위 조건의 SQL 질의문은 대략 다음과 같습니다. :: SELECT id, username, first_name, last_name, email FROM auth_user WHERE NOT id < 5; .. image:: sqluser_notquery.png -Method 1 using exclude +exclude 메서드를 이용하는 방법은 다음과 같습니다. .. code-block @@ -32,7 +32,7 @@ Method 1 using exclude >>> queryset , , , , , ]> -Method 2 using Q() method :: +Q 객체를 이용하는 방법은 다음과 같습니다. :: >>> from django.db.models import Q >>> queryset = User.objects.filter(~Q(id__lt=5)) From 797fac15dcdd7cc8849dcdbdd8a8eb27d80bc823 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sat, 29 Sep 2018 21:17:37 +0900 Subject: [PATCH 033/100] union --- docs/union.rst | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/docs/union.rst b/docs/union.rst index 726fa93..0345fea 100644 --- a/docs/union.rst +++ b/docs/union.rst @@ -1,10 +1,10 @@ -같은 모델 또는 다른 모델에서의 2개의 쿼리셋을 어떻게 합칠까(union)? -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +동일한 모델 또는 서로 다른 모델에서 구한 쿼리셋들의 합집합을 구하는 방법은 무엇인가요? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -union은 2개 이상의 쿼리셋 결과물을 합칠 때 사용됩니다. -쿼리셋은 같거나 다른 모델에서 만들 수 있습니다. 만약 다른 모델을 통해 얻은 쿼리셋이라면, 필드와 데이터 타입을 맞춰야만 합니다. +SQL에서는 여러 개의 결과 집합을 합할 때 UNION 연산을 이용합니다. 장고 ORM에서 union 메서드를 이용해 쿼리셋을 합할 수 있습니다. 합하려는 쿼리셋의 모델이 서로 다른 경우, 각 쿼리셋에 포함된 필드와 데이터 유형이 서로 맞아야 합니다. -:code:`auth_user` 을 통해 계속 보도록 합시다. 이 모델로부터 union을 하기 위해 2개의 쿼리셋을 생성하겠습니다. + +:code:`auth_user` 모델에서 두 쿼리셋을 구한 뒤 합집합을 구해 봅시다. .. code-block:: python @@ -19,7 +19,7 @@ union은 2개 이상의 쿼리셋 결과물을 합칠 때 사용됩니다. >>> q2.union(q1) , , , , , , , , , ]> -자, 해봅시다. +다음 코드는 실행하면 오류가 발생합니다. .. code-block:: python @@ -30,13 +30,11 @@ union은 2개 이상의 쿼리셋 결과물을 합칠 때 사용됩니다. django.db.utils.OperationalError: SELECTs to the left and right of UNION do not have the same number of result columns -union은 오직 같은 필드와 같은 데이터타입을 갖는 쿼리셋으로 실행할 수 있습니다. 그렇기 때문에 위 마지막에 error를 만나게 된 겁니다. 같은 필드 쿼리셋이면 2개 모델에서 union을 실행할 수 있습니다. - -:code:`Hero` 와 :code:`Villain` 두 개 모델 모두 :code:`name` 과 :code:`gender` 를 가지고 있기 때문에 -우리는 2개 필드로 제한하기 위해 :code:`values_list` 를 사용한 후 union을 할 수 있습니다. +union 메서드는 합하려는 쿼리셋의 필드와 데이터 유형이 서로 일치할 때만 실행할 수 있습니다. 그래서 마지막 명령이 실패했습니다. +:code:`Hero` 모델과 :code:`Villain` 모델은 둘 다 :code:`name` 필드와 :code:`gender` 필드를 갖고 있습니다. :code:`values_list`를 이용해 공통된 필드만 가져온 뒤 union을 수행할 수 있습니다. -.. code-block:: python +... code-block:: python Hero.objects.all().values_list( "name", "gender" @@ -45,4 +43,5 @@ union은 오직 같은 필드와 같은 데이터타입을 갖는 쿼리셋으 "name", "gender" )) -위 코드를 통해 :code:`Hero` 와 :code:`Villain` 모델의 name과 gender 모두를 얻게 될 것입니다. +위 코드를 실행하면 :code:`Hero` 모델과 :code:`Villain` 모델의 이름과 성별을 함꼐 구할 수 있습니다. + From 43e835800211decf0b731c3bb97162fdb3d6bc71 Mon Sep 17 00:00:00 2001 From: Taehwa Kang Date: Sat, 29 Sep 2018 21:34:25 +0900 Subject: [PATCH 034/100] =?UTF-8?q?Django=20ORM=20cookbook=20Chapter=202.1?= =?UTF-8?q?4=20=EB=B6=80=ED=84=B0=20Chapter=202.17=EA=B9=8C=EC=A7=80=20?= =?UTF-8?q?=EB=B2=88=EC=97=AD.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Taehwa Kang --- docs/aggregation.rst | 4 ++-- docs/func_expressions.rst | 18 +++++++++--------- docs/query_relatedtool.rst | 14 +++++++------- docs/random.rst | 22 +++++++++++----------- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/docs/aggregation.rst b/docs/aggregation.rst index 51b5232..c059537 100644 --- a/docs/aggregation.rst +++ b/docs/aggregation.rst @@ -1,7 +1,7 @@ -How to group records in Django ORM? +Django ORM을 사용하여 어떻게 기록을 집계할 수 있나요? ======================================== -Grouping of records in Django ORM can be done using aggregation functions like :code:`Max`, :code:`Min`, :code:`Avg`, :code:`Sum`. Django queries help to create, retrieve, update and delete objects. But sometimes we need to get aggregated values from the objects. We can get them by example shown below :: +:code:`Max`, :code:`Min`, :code:`Avg`, :code:`Sum` 과 같은 집계함수를 사용하면 Django ORM을 사용하여 기록을 집계할 수 있습니다. Django 쿼리를 통해 객체를 생성하고 읽고 갱신하고 삭제할 수 있지만 이 뿐 아니라 기록들을 집계해야 할 때가 있습니다. 다믕과 같은 방법을 통해 기록을 집계할 수 있습니다. :: >>> from django.db.models import Avg, Max, Min, Sum, Count >>> User.objects.all().aggregate(Avg('id')) diff --git a/docs/func_expressions.rst b/docs/func_expressions.rst index dcf4ae0..012e347 100644 --- a/docs/func_expressions.rst +++ b/docs/func_expressions.rst @@ -1,14 +1,14 @@ -How to use arbitrary database functions in querysets? +어떻게 쿼리셋에서 데이터베이스의 특정한 함수를 사용할 수 있나요? ======================================================================== -Django comes with functions like :code:`Lower`, :code:`Coalesce` and :code:`Max`, but it can't support all database functions, expecially ones which are database specific. +Django에서도 :code:`Lower`, :code:`Coalesce`, :code:`Max` 와 같은 함수를 제공하지만 모든 데이터베이스의 함수를 제공하지는 않습니다. 각 데이터베이스의 특징적인 함수들은 더욱 더 그렇습니다. -Django provides :code:`Func` which allows using arbitrary database functions, even if Django doesn't provide them. +Django에서는 Django에서 제공하지 않는 특정한 데이터베이스 함수를 사용할 수 있게 해주는 :code:`Func` 함수를 제공합니다. -Postgres has :code:`fuzzystrmatch`, which provides several functions to determine similarities. Install the extension in your postgres DB with :code:`create extension fuzzystrmatch` +Postgres는 유사성을 측정하는 몇가지 함수의 모음인 :code:`fuzzystrmatch` 가 있습니다. :code:`create extension fuzzystrmatch` 명령으로 postgres DB에 이를 설치할 수 있습니다. -We will use the :code:`levenshtein` function. Lets first create some Hero objects. +Postgres의 :code:`levenshtein` 함수를 사용해봅시다. 먼저 Hero 객체를 몇 개 만들어 봅시다. .. code-block:: python @@ -18,7 +18,7 @@ We will use the :code:`levenshtein` function. Lets first create some Hero object Hero.objects.create(name="Xeus", description="A greek God", benevolence_factor=80, category_id=12, origin_id=1) Hero.objects.create(name="Poseidon", description="A greek God", benevolence_factor=80, category_id=12, origin_id=1) -We want to find out the :code:`Hero` objects which have :code:`name` similar to Zeus. You can do +이 때 이름(:code:`name`)이 Zeus와 유사한 :code:`Hero` 객체를 찾고 싶다면 다음과 같이 할 수 있습니다. .. code-block:: python @@ -26,7 +26,7 @@ We want to find out the :code:`Hero` objects which have :code:`name` similar to Hero.objects.annotate(like_zeus=Func(F('name'), function='levenshtein', template="%(function)s(%(expressions)s, 'Zeus')")) -The :code:`like_zeus=Func(F('name'), function='levenshtein', template="%(function)s(%(expressions)s, 'Zeus')")` took two arguments which allowed the database representation, viz, :code:`function` and :code:`template`. If you need to reuse the function, you can define a class like this. +:code:`like_zeus=Func(F('name'), function='levenshtein', template="%(function)s(%expressions)s, 'Zeus')")` 는 function과 template, 두 인자를 받습니다. 만약 이 함수를 재사용하고 싶다면 다음과 같은 클래스를 정의하면 됩니다. .. code-block:: python @@ -34,9 +34,9 @@ The :code:`like_zeus=Func(F('name'), function='levenshtein', template="%(functio function='levenshtein' template="%(function)s(%(expressions)s, 'Zeus')" -And then use :code:`Hero.objects.annotate(like_zeus=LevenshteinLikeZeus(F("name")))` +이제 이것을 :code:`Hero.objects.annotate(like_zeus=LevenshteinLikeZeus(F("name")))` 과 같이 사용하면 됩니다. -You can then filter on this annotated field like this. +이렇게 생성된 :code:`like_zeus` 필드를 다음과 같이 필터링할 수 있습니다. .. code-block:: ipython diff --git a/docs/query_relatedtool.rst b/docs/query_relatedtool.rst index 150b086..0d4e273 100644 --- a/docs/query_relatedtool.rst +++ b/docs/query_relatedtool.rst @@ -1,9 +1,9 @@ -How to use :code:`Q` objects for complex queries? +어떻게 복잡한 쿼리에 :code:`Q` 객체를 사용하나요? ================================================== -In previous chapters we used :code:`Q` objects for :code:`OR` and :code:`AND` and :code:`NOT` operations. :code:`Q` objects provides you complete control over the where clause of the query. +지난 장에서 :code:`Q` 객체를 :code:`OR` 와 :code:`AND` 그리고 :code:`NOT` 연산에 사용했습니다. :code:`Q` 객체를 사용하면 어떤 쿼리의 Where절을 쉽게 나타낼 수 있습니다. -If you want to :code:`OR` your conditions. +만약 :code:`OR` 연산을 하고 싶다면, .. code-block:: ipython @@ -14,7 +14,7 @@ If you want to :code:`OR` your conditions. >>> queryset , , , , ]> -If you want to :code:`AND` your conditions. +만약 :code:`AND` 연산을 하고 싶다면, .. code-block:: ipython @@ -24,7 +24,7 @@ If you want to :code:`AND` your conditions. >>> queryset , , ]> -If you want to find all users whose :code:`first_name` starts with 'R', but not if the :code:`last_name` has 'Z' +만약 이름(:code:`first_name`)이 'R'로 시작하면서 성(:code:`last_name`)은 'Z'로 시작하지 않는 모든 유저를 찾고 싶다면 .. code-block:: ipython @@ -33,7 +33,7 @@ If you want to find all users whose :code:`first_name` starts with 'R', but not ) -If you look at the generated query, you would see +이때 생성된 쿼리는 다음과 같습니다. .. code-block:: sql @@ -52,4 +52,4 @@ If you look at the generated query, you would see WHERE ("auth_user"."first_name"::text LIKE R% AND NOT ("auth_user"."last_name"::text LIKE Z%)) -You can combine the Q objects in more complex ways to generate complex queries. +더 복잡한 형태의 쿼리들도 Q객체들을 조합하여 얼마든지 나타낼 수 있습니다. diff --git a/docs/random.rst b/docs/random.rst index 37f7d62..fafc57c 100644 --- a/docs/random.rst +++ b/docs/random.rst @@ -1,7 +1,7 @@ -How to efficiently select a random object from a model? +어떻게 한 모델에서 임의의 객체를 효율적으로 선택할 수 있나요? ======================================================================== -Your :code:`category` models is like this. +:code:`category` 모델이 다음과 같이 정의되어 있습니다. .. code-block:: python @@ -15,16 +15,16 @@ Your :code:`category` models is like this. return self.name -You want to get a random Category. We will look at few alternate ways to do this. +이 Category 모델에서 임의의 객체를 선택하는 몇 가지 방법을 살펴보겠습니다. -The most straightforward way, you can :code:`order_by` random and fetch the first record. It would look something like this. +가장 직관적인 방법은 임의의 기준으로 정렬(:code:`order_by`)한 뒤에 첫번째 객체를 선택하는 것입니다. 다음과 같이 할 수 있습니다. .. code-block:: python def get_random(): return Category.objects.order_by("?").first() -Note: :code:`order_by('?')` queries may be expensive and slow, depending on the database backend you’re using. To test other methods, we need to insert one million records in :code:`Category` table. Go to your db like with :code:`python manage.py dbshell` and run this. +참고: :code:`order_by('?')` 쿼리는 사용하고 있는 데이터베이스에 따라 느리고 비효율적일 수 있습니다. 다른 방법을 테스트하기에 앞서서 100만개의 데이터를 :code:`Category` 에 추가해봅시다. :code:`python manage.py dbshell` 과 같은 명령어를 통해 db로 이동하여 다음 구문을 실행합시다. .. code-block:: sql @@ -33,10 +33,10 @@ Note: :code:`order_by('?')` queries may be expensive and slow, depending on the (SELECT Md5(Random() :: text) AS descr FROM generate_series(1, 1000000)); -You don't need to understand the full details of the sql above, it creates one million numbers and :code:`md5-s` them to generate the name, then inserts it in the DB. +위 코드를 완전히 이해할 필요는 없습니다. 위 코드는 백만개의 숫자를 생성하여 :code:`md5-s` 로 해시한 뒤 그 값을 name에 넣어 db에 저장하는 일을 합니다. -Now, instead of sorting the whole table, you can get the max id, -generate a random number in range [1, max_id], and filter that. You are assuming that there have been no deletions. +이제 전체 테이블을 정령하지 않고도 max_id를 구한 뒤 [1, max_id]사이의 임의의 숫자를 생성한 뒤 필터링하여 임의의 객체를 선택할 수 있습니다. +다만 이 방법은 db에서 삭제 연산이 없었다는 가정에만 성립합니다. .. code-block:: python @@ -58,7 +58,7 @@ generate a random number in range [1, max_id], and filter that. You are assuming In [6]: get_random2() Out[6]: -If your models has deletions, you can slightly modify the functions, to loop until you get a valid :code:`Category`. +만약 삭제 연산이 있었다면, 유효한 :code:`Category` 객체를 찾을 때까지 반복하도록 코드를 수정하면 됩니다. .. code-block:: python @@ -77,7 +77,7 @@ If your models has deletions, you can slightly modify the functions, to loop unt In [10]: get_random3() Out[10]: -Unless your model has a lot of deletions, the :code:`while True:` loop return quickly. Lets use :code:`timeit` to see the differences. +많은 삭제 연산이 이루어지지 않았다면 :code:`while True:` 는 금세 return할 것입니다. :code:`timeit` 을 사용하여 시간을 비교해봅시다. .. code-block:: python @@ -87,6 +87,6 @@ Unless your model has a lot of deletions, the :code:`while True:` loop return qu In [15]: timeit.timeit(get_random, number=100) Out[15]: 56.92513192095794 -:code:`get_random3` is about 283 time faster than :code:`get_random`. :code:`get_random` is the most generic way, but the technique in :code:`get_random3` will work unless you change changed the default way Django generates the id - autoincrementing integers, or there have been too many deletions. +:code:`get_random3` 가 약 283배나 더 빠르게 나타납니다. :code:`get_random` 이 가장 일반적으로 사용할 수 있는 방법이지만 삭제연산이 많이 이루어지지 않았다면 :code:`get_random3` 의 방법을 사용하는 것이 훨씬 효율적일 수 있습니다. From ffa50996aad8f6d03f46a6630825cf6ff31e558c Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sat, 29 Sep 2018 21:36:28 +0900 Subject: [PATCH 035/100] select_some_fields --- docs/select_some_fields.rst | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/docs/select_some_fields.rst b/docs/select_some_fields.rst index 1165f4d..76ac09c 100644 --- a/docs/select_some_fields.rst +++ b/docs/select_some_fields.rst @@ -1,16 +1,16 @@ -How to select some fields only in a queryset? -++++++++++++++++++++++++++++++++++++++++++++++++++ +쿼리셋의 일부 필드만 조회하려면 어떻게 하나요? ++++++++++++++++++++++++++++++++++++++++++++++++++++++ .. image:: usertable.png -The :code:`auth_user` model has a number of fields in it. But sometimes, you do not need to use all the fields. In such situations, we can query only desired fields. +:code:`auth_user` 모델에는 여러 개의 필드가 들어 있습니다. 그런데 이 필드가 전부 다 필요하지 않을 때도 있죠. 그럴 떄 필요한 필드만 읽어오는 방법을 알아 봅시다. -Django provides two ways to do this +장고는 두 가지 방법을 제공합니다. -- `values` and `values_list` methods on queryset. -- `only_method` +- 쿼리셋의 `values` 메서드와 `values_list` 메서드 +- `only` 메서드 -Say, we want to get :code:`first_name` and :code:`last_name` of all the users whose name starts with **R**. You do not want the fetch the other fields to reduce the work the DB has to do. +이름이 R로 시작하는 모든 사용자의 :code:`first_name`과 :code:`last_name`을 구해 봅시다. 데이터베이스 시스템의 부하를 줄이기 위해 그 외의 필드는 가져오지 않겠습니다. .. code-block:: python @@ -19,16 +19,16 @@ Say, we want to get :code:`first_name` and :code:`last_name` of all the users wh ).values('first_name', 'last_name') Date: Sat, 29 Sep 2018 21:57:33 +0900 Subject: [PATCH 036/100] subquery --- docs/subquery.rst | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/docs/subquery.rst b/docs/subquery.rst index 854dcab..5f23fbd 100644 --- a/docs/subquery.rst +++ b/docs/subquery.rst @@ -1,8 +1,7 @@ -How to do a subquery expression in Django? -============================================= +장고에서 서브쿼리 식을 사용하려면 어떻게 하나요? +============================================================== -Django allows using SQL subqueries. -Let's start with something simple, We have a :code:`UserParent` model which has :code:`OnetoOne` relation with auth user. We will find all the :code:`UserParent` which have a :code:`UserParent`. +장고에서 SQL 서브쿼리 식을 사용할 수 있습니다. 간단한 것부터 시작해 봅시다. :code:`auth_user` 모델과 일 대 일(:code:`OneToOne`) 관계로 연결된 :code:`UserParent` 모델이 있다고 합시다. 아래 코드로 ``UserParent`` 모델에서 ``auth_user``를 가진 행을 모두 구할 수 있습니다. .. code-block:: ipython @@ -11,9 +10,9 @@ Let's start with something simple, We have a :code:`UserParent` model which has >>> UserParent.objects.filter(user_id__in=Subquery(users.values('id'))) , , ]> -Now for something more complex. For each :code:`Category`, we want to find the most benevolent :code:`Hero`. +조금 더 까다로운 예제를 살펴봅시다. :code:`Category` 모델의 각 행 별로, 가장 선한 :code:`Hero` 행을 구해 봅시다. -The models look something like this. +모델은 다음과 같이 준비합니다. .. code-block:: python @@ -32,7 +31,7 @@ The models look something like this. ) -You can find the most benevolent Hero like this +이 모델에서 가장 관대한 영웅을 구하려면 다음 코드를 실행합니다. .. code-block:: python @@ -45,7 +44,7 @@ You can find the most benevolent Hero like this ) ) -If you look at the generated sql, you will see +이 코드가 실행하는 SQL 질의문은 다음과 같습니다. .. code-block:: sql @@ -60,7 +59,7 @@ If you look at the generated sql, you will see FROM "entities_category" -Let's break down the queryset logic. The first part is +질의문을 한 단계씩 나누어 살펴봅시다. 다음 코드가 첫 번쨰 단계입니다. .. code-block:: python @@ -68,9 +67,8 @@ Let's break down the queryset logic. The first part is category=OuterRef("pk") ).order_by("-benevolence_factor") -We are ordering the :code:`Hero` object by :code:`benevolence_factor` in DESC order, and using -:code:`category=OuterRef("pk")` to declare that we will be using it in a subquery. +:code:`Hero`의 행들을 선함(:code:`benevolence_factor`)에 따라 내림차순(DESC)으로 정렬하여 선택합니다. 그리고 :code:`category=OuterRef("pk")`를 이용해 이 선택이 서브쿼리로 사용될 수 있도록 준비합니다. -Then we annotate with :code:`most_benevolent_hero=Subquery(hero_qs.values('name')[:1])`, to get use the subquery with a :code:`Category` queryset. The :code:`hero_qs.values('name')[:1]` part picks up the first name from subquery. +그 뒤 :code:`most_benevolent_hero=Subquery(hero_qs.values('name')[:1])`로 서브쿼리에 별칭을 붙여 :code:`Category` 쿼리셋 안에서 사용합니다. 이 때, :code:`hero_qs.values('name')[:1]`는 서브쿼리에서 첫 번째 행의 name 필드를 구하는 코드입니다. From 4324bd720513985994831e602a1b487108279781 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sat, 29 Sep 2018 21:58:50 +0900 Subject: [PATCH 037/100] subquery --- docs/subquery.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/subquery.rst b/docs/subquery.rst index 5f23fbd..52c12be 100644 --- a/docs/subquery.rst +++ b/docs/subquery.rst @@ -1,7 +1,7 @@ 장고에서 서브쿼리 식을 사용하려면 어떻게 하나요? ============================================================== -장고에서 SQL 서브쿼리 식을 사용할 수 있습니다. 간단한 것부터 시작해 봅시다. :code:`auth_user` 모델과 일 대 일(:code:`OneToOne`) 관계로 연결된 :code:`UserParent` 모델이 있다고 합시다. 아래 코드로 ``UserParent`` 모델에서 ``auth_user``를 가진 행을 모두 구할 수 있습니다. +장고에서 SQL 서브쿼리 식을 사용할 수 있습니다. 간단한 것부터 시작해 봅시다. :code:`auth_user` 모델과 일 대 일(:code:`OneToOne`) 관계로 연결된 :code:`UserParent` 모델이 있다고 합시다. 아래 코드로 :code:`UserParent` 모델에서 :code:`auth_user`를 가진 행을 모두 구할 수 있습니다. .. code-block:: ipython From 3fa19affabafbe684279de6ee406f449e1378619 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sat, 29 Sep 2018 22:16:30 +0900 Subject: [PATCH 038/100] f_query --- docs/f_query.rst | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/f_query.rst b/docs/f_query.rst index ece0dae..d00507c 100644 --- a/docs/f_query.rst +++ b/docs/f_query.rst @@ -1,11 +1,12 @@ -필드 값 비교를 기준으로 쿼리셋 필터링 하기 +필드의 값을 서로 비교하여 행을 선택하려면 어떻게 하나요? ============================================================================== -Django ORM은 고정된 값으로 필터링하는 것을 도와줍니다. -:code:`first_name` 이 :code:`'R'` 로 시작하는 :code:`User` Object를 얻기 위해 -:code:`User.objects.filter(first_name__startswith='R')` 를 쓸 수 있습니다. -만약 first_name과 last_name을 비교하고 싶다면 :code:`F` obejct를 쓸 수 있습니다. -먼저 user를 만들어보겠습니다. +장고 ORM에서 특정한 값을 기준으로 행을 선택하는 것은 간단합니다. 예를 들어, :code:`first_name`이 :code:`'R'`로 시작하는 :code:`User` 모델의 행을 구하려면 +:code:`User.objects.filter(first_name__startswith='R')`와 같이 코드를 작성하면 됩니다. + +그런데 first_name을 last_name과 비교하여 선택하려면 어떻게 해야 할까요? 이럴 때 :code:`F` 객체를 사용합니다. + +실습을 위해 User 행을 몇 개 생성합시다. .. code-block:: ipython @@ -16,7 +17,7 @@ Django ORM은 고정된 값으로 필터링하는 것을 도와줍니다. In [28]: User.objects.create_user(email="guido@example.com", username="Guido", first_name="Guido", last_name="Guido") Out[28]: -이제 fisrt_name과 last_name이 같은 유저를 찾을 수 있습니다. +실습 데이터가 준비되었으면, 다음 코드로 이름과 성이 동일한 사용자를 구해 봅시다. .. code-block:: ipython @@ -24,8 +25,7 @@ Django ORM은 고정된 값으로 필터링하는 것을 도와줍니다. In [29]: User.objects.filter(last_name=F("first_name")) Out[29]: ]> -:code:`F` object는 annotate를 사용하여 계산된 필드에서도 사용할 수 있습니다. -만약 first_name과 last_name의 첫글자가 같은 유저를 찾길 원한다면 :code:`Substr("first_name", 1, 1)` 를 사용할 수 있습니다. +:code:`F` 객체는 annotate 메서드로 계산해 둔 필드를 가리킬 때도 사용할 수 있습니다. 예를 들어, 이름의 첫 글자와 성의 첫 글자가 동일한 사용자를 구하고 싶다면 :code:`Substr("first_name", 1, 1)`를 사용할 수 있습니다. .. code-block:: ipython @@ -35,5 +35,5 @@ Django ORM은 고정된 값으로 필터링하는 것을 도와줍니다. In [46]: User.objects.annotate(first=Substr("first_name", 1, 1), last=Substr("last_name", 1, 1)).filter(first=F("last")) Out[46]: , ]> -또한 :code:`F` object는 :code:`__gt`, :code:`__lt` 나 다른 expression과 함께 사용 가능합니다. +:code:`F` 객체에 :code:`__gt`, :code:`__lt` 등의 식을 적용하는 것 또한 가능합니다. From e28bf1ebaf0f4e9e8815c4f792c694db869214b3 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sat, 29 Sep 2018 22:19:12 +0900 Subject: [PATCH 039/100] filefield --- docs/filefield.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/filefield.rst b/docs/filefield.rst index 70dd31c..3a68b9f 100644 --- a/docs/filefield.rst +++ b/docs/filefield.rst @@ -1,7 +1,7 @@ -어떻게 파일이 없는 Object를 FileField로 필터링 하나요? -++++++++++++++++++++++++++++++++++++++++++++++ +FileField에 파일이 들어있지 않은 행을 구하려면 어떻게 하나요? +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -:code:`FileField` 나 :code:`ImageField` 는 파일이나 이미지의 경로를 저장합니다. Database 레벨에선 둘 모두 :code:`CharField` 로 같습니다. 아래의 쿼리로 파일이 없는 object를 찾을 수 있습니다. +장고의 :code:`FileField`와 :code:`ImageField`는 파일과 이미지 파일의 경로를 저장합니다. 이것은 응용 수준에서의 구별이고, 데이터베이스 수준에서는 모두 :code:`CharField`와 동일한 방식으로 저장됩니다. 파일이 없는 행을 구하려면 다음 코드를 실행하면 됩니다. .. code-block:: python From 744cd58b395118b6a3c7ba4ed0331b27b7cc8c59 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sat, 29 Sep 2018 22:26:10 +0900 Subject: [PATCH 040/100] join --- docs/join.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/join.rst b/docs/join.rst index c5b360c..f93d3f2 100644 --- a/docs/join.rst +++ b/docs/join.rst @@ -1,7 +1,7 @@ -Django ORM에서 join 연산이 어떻게 작동하나요? -====================================================== +두 모델을 결합하려면 어떻게 하나요? +======================================================== -SQL Join문은 둘 이상의 테이블 사이에서 공통 필드를 기반으로 데이터 혹은 행을 결합하는 데 사용됩니다. Join은 여러 방법으로 수행될 수 있으며 몇가지 예시는 아래와 같습니다. :: +SQL에서는 JOIN 문을 이용해 동일한 값을 가진 열을 기준으로 두 표를 결합할 수 있습니다. 결합 연산은 여러 가지 방법으로 수행할 수 있습니다. 다음은 장고에서 이를 수행하는 몇 가지 예입니다. :: >>> a1 = Article.objects.select_related('reporter') // Using select_related >>> a1 From 5ddeabe26889b40a2a0278e4009f8403609e356b Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sat, 29 Sep 2018 22:45:30 +0900 Subject: [PATCH 041/100] second_largest 1 --- docs/second_largest.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/second_largest.rst b/docs/second_largest.rst index 5537c55..c046bd3 100644 --- a/docs/second_largest.rst +++ b/docs/second_largest.rst @@ -1,12 +1,13 @@ -어떻게 두번째로 큰 record를 찾을 수 있나요? +두번째로 큰 행을 구하려면 어떻게 하나요? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -연령이나 급여에 따라 두 번째로 높은 사용자를 찾고 싶은 경우가 있습니다. -Django ORM은 :code:`first()` 나 :code:`last()` 와 같은 방식으로 첫번째나 마지막 항목을 찾을 수 있는 유연성을 제공하지만 n번째 항목은 찾을 수 없습니다. 그럴때 slice 연산자를 사용하면 가능합니다 +예컨대 나이·급여 등이 두번째로 많은 사용자를 찾아야 하는 경우가 있습니다. + +장고 ORM에서 첫번째 항목은 :code:`first()` 메서드로, 마지막 항목은 :code:`last()` 메서드로 구할 수 있습니다. 하지만 N번째 항목을 구하는 메서드는 제공되지 않습니다. 그 대신, 파이썬의 인덱싱 연산을 이용하면 됩니다. .. image:: usertable.png -slice 연산자를 사용하여 N번째 record를 찾을 수 있습니다. +아래 코드와 같이, 인덱싱 연산을 이용해 정렬된 데이터베이스에서 N번째 항목을 구할 수 있습니다. .. code-block:: python From fe1902fbf0b44c5c9a1254b79d0ba1a203f7875d Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 03:09:46 +0900 Subject: [PATCH 042/100] second_largest 1 --- docs/second_largest.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/second_largest.rst b/docs/second_largest.rst index c046bd3..77eb79c 100644 --- a/docs/second_largest.rst +++ b/docs/second_largest.rst @@ -1,4 +1,4 @@ -두번째로 큰 행을 구하려면 어떻게 하나요? +두번째로 큰 항목은 어떻게 구하죠? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 예컨대 나이·급여 등이 두번째로 많은 사용자를 찾아야 하는 경우가 있습니다. From 58c0981b8bde3ce8eaecce5052029f3c6c443381 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 03:15:59 +0900 Subject: [PATCH 043/100] second_largest 2 --- docs/second_largest.rst | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/docs/second_largest.rst b/docs/second_largest.rst index 77eb79c..48cff4b 100644 --- a/docs/second_largest.rst +++ b/docs/second_largest.rst @@ -1,13 +1,13 @@ 두번째로 큰 항목은 어떻게 구하죠? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -예컨대 나이·급여 등이 두번째로 많은 사용자를 찾아야 하는 경우가 있습니다. +어떤 필드를 기준으로 데이터를 정렬했을 때, 두 번째 항목을 구해야 하는 경우가 있습니다. 예컨대, 나이·급여 등이 두번째로 많은 사용자를 찾아야 하는 경우가 있겠죠. -장고 ORM에서 첫번째 항목은 :code:`first()` 메서드로, 마지막 항목은 :code:`last()` 메서드로 구할 수 있습니다. 하지만 N번째 항목을 구하는 메서드는 제공되지 않습니다. 그 대신, 파이썬의 인덱싱 연산을 이용하면 됩니다. +장고 ORM에서 첫번째 항목은 :code:`first()` 메서드로, 마지막 항목은 :code:`last()` 메서드로 구할 수 있습니다. 하지만 N번째 항목을 구하는 메서드는 제공되지 않습니다. 그 대신, 파이썬의 인덱싱 연산을 이용할 수 있습니다. .. image:: usertable.png -아래 코드와 같이, 인덱싱 연산을 이용해 정렬된 데이터베이스에서 N번째 항목을 구할 수 있습니다. +아래 코드와 같이, 인덱싱 연산으로 정렬된 데이터의 N번째 항목을 구할 수 있습니다. .. code-block:: python @@ -19,9 +19,7 @@ 'Sohan' -:code:`User.objects.order_by('-last_login')[2]` 해당 쿼리는 Database로 부터 세번째로 큰 결과만 가져오는 SQL구문을 생성합니다. -:code:`LIMIT ... OFFSET` 쿼리로 부터 생성된 SQL구문의 LIMIT ... OFFSET 부분을 확인할 수 있습니다. - +:code:`User.objects.order_by('-last_login')[2]`와 같이 쿼리셋에 인덱스 연산을 지시할 때, 장고 ORM은 데이터베이스에서 전체 데이터를 가져온 뒤 인덱싱하는 것이 아니라, :code:`LIMIT ... OFFSET` SQL 구문을 이용해 필요한 데이터만 읽어 옵니다. 실제로 생성되는 SQL 질의문을 살펴봅시다. .. code-block:: sql From 3baf91fbfea0afb76866c038dbef7a555c8d9d86 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 03:22:58 +0900 Subject: [PATCH 044/100] duplicate --- docs/duplicate.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/duplicate.rst b/docs/duplicate.rst index e28de1c..9204b98 100644 --- a/docs/duplicate.rst +++ b/docs/duplicate.rst @@ -1,9 +1,9 @@ -중복된 필드 값 갖는 열 찾기 +특정 열의 값이 동일한 항목은 어떻게 찾나요? ============================================== .. image:: usertable2.png -:code:`first_name` 이 일치하는 user들을 찾길 원한다고 가정해봅시다. 아래의 쿼리로 중복된 필드 값을 갖는 record들을 찾을 수 있습니다. +:code:`first_name`이 서로 동일한 사용자들을 구한다고 합시다. 특정 열에서 중복된 값을 찾을 때는 아래와 같이 :code:`Count`를 구한 뒤 중복 수를 기준으로 골라내면 됩니다. .. code-block:: python @@ -13,7 +13,8 @@ >>> duplicates -위의 쿼리에 해당하는 모든 record들의 id를 찾기위해 아래와 같은 쿼리를 쓸 수 있습니다. +위와 같이 중복 값을 구했으면, 이 값을 가진 항목을 아래와 같이 구할 수 있습니다. + .. code-block:: python From 421180a218ba7ddc8bd623a76421a439274c4674 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 03:29:46 +0900 Subject: [PATCH 045/100] distinct --- docs/distinct.rst | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/distinct.rst b/docs/distinct.rst index 61f0515..a4cab81 100644 --- a/docs/distinct.rst +++ b/docs/distinct.rst @@ -1,10 +1,9 @@ -How to find distinct field values from queryset? -어떻게 쿼리셋에서 중복되지 않는 필드 값을 찾나요? +쿼리셋에서 고유한 필드 값을 가진 항목은 어떻게 구하나요? ======================================================================== .. image:: usertable2.png -first_name이 중복되지 않는 유저를 찾기위해 아래와 같은 쿼리를 사용할 수 있습니다. +이름이 다른 사용자와 겹치지 않은 사용자를 찾는다고 합시다. 다음과 같이 구할 수 있습니다. .. code-block:: python @@ -15,5 +14,5 @@ first_name이 중복되지 않는 유저를 찾기위해 아래와 같은 쿼리 ).filter(name_count=1) records = User.objects.filter(first_name__in=[item['first_name'] for item in distinct]) -:code:`User.objects.distinct("first_name").all()`, 의 경우 중복된 :code:`first_name` 을 갖는 유저들 중 최초 유저를 가져오므로 위의 쿼리와 차이가 있습니다. +한편, :code:`User.objects.distinct("first_name").all()`와 같은 코드는 고유한 :code:`first_name`을 가진 사용자 중 첫번째 항목을 구하는 코드입니다. 위 코드와는 실행 결과가 다릅니다. From c1d4a16ba0e67d22794d1d8f032652a4e024b807 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 03:36:56 +0900 Subject: [PATCH 046/100] query_relatedtool --- docs/query_relatedtool.rst | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/docs/query_relatedtool.rst b/docs/query_relatedtool.rst index 150b086..2119159 100644 --- a/docs/query_relatedtool.rst +++ b/docs/query_relatedtool.rst @@ -1,9 +1,9 @@ -How to use :code:`Q` objects for complex queries? -================================================== +Q 객체를 이용해 복잡한 질의를 수행하는 방법은 무엇인가요? +==================================================================== -In previous chapters we used :code:`Q` objects for :code:`OR` and :code:`AND` and :code:`NOT` operations. :code:`Q` objects provides you complete control over the where clause of the query. +앞선 몇 개의 장에서 :code:`Q` 객체를 이용해 :code:`OR` 연산, :code:`AND` 연산, :code:`NOT` 연산을 수행해 보았습니다. :code:`Q` 객체를 이용하면 SQL 질의문의 WHERE 절에 해당하는 기능을 온전히 활용할 수 있습니다. -If you want to :code:`OR` your conditions. +조건식에서 :code:`OR` 연산을 수행하려면 다음과 같이 합니다. .. code-block:: ipython @@ -14,7 +14,7 @@ If you want to :code:`OR` your conditions. >>> queryset , , , , ]> -If you want to :code:`AND` your conditions. +조건식에서 :code:`AND` 연산을 수행하려면 다음과 같이 합니다. .. code-block:: ipython @@ -24,7 +24,7 @@ If you want to :code:`AND` your conditions. >>> queryset , , ]> -If you want to find all users whose :code:`first_name` starts with 'R', but not if the :code:`last_name` has 'Z' +:code:`first_name`이 'R'로 시작하되, :code:`last_name`에 'Z'가 포함되지 않은 사용자를 모두 구하려면 다음과 같이 조건을 작성하면 됩니다. .. code-block:: ipython @@ -32,8 +32,7 @@ If you want to find all users whose :code:`first_name` starts with 'R', but not Q(first_name__startswith='R') & ~Q(last_name__startswith='Z') ) - -If you look at the generated query, you would see +다음은 위 코드에서 장고가 생성하는 질의문입니다. .. code-block:: sql @@ -52,4 +51,4 @@ If you look at the generated query, you would see WHERE ("auth_user"."first_name"::text LIKE R% AND NOT ("auth_user"."last_name"::text LIKE Z%)) -You can combine the Q objects in more complex ways to generate complex queries. +Q 객체를 이용하면 이보다 더 복잡한 조건의 질의도 문제 없이 지시할 수 있습니다. From 0320bc0e251e29a361765997ff5b4508b27046a9 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 03:41:12 +0900 Subject: [PATCH 047/100] aggregation --- docs/aggregation.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/aggregation.rst b/docs/aggregation.rst index 51b5232..5586d62 100644 --- a/docs/aggregation.rst +++ b/docs/aggregation.rst @@ -1,7 +1,7 @@ -How to group records in Django ORM? -======================================== +항목들을 집계하는 방법은 무엇인가요? +=========================================== -Grouping of records in Django ORM can be done using aggregation functions like :code:`Max`, :code:`Min`, :code:`Avg`, :code:`Sum`. Django queries help to create, retrieve, update and delete objects. But sometimes we need to get aggregated values from the objects. We can get them by example shown below :: +장고 ORM을 이용해 항목을 생성·조회·갱신·삭제할 수 있지만, 때로는 항목들의 집계값을 구하고 싶을 때가 있습니다. 장고 ORM에는 SQL의 일반적인 집계 기능을 수행하는 :code:`Max`, :code:`Min`, :code:`Avg`, :code:`Sum` 등의 함수가 있습니다. 다음은 이 집계 함수를 이용하는 예입니다. :: >>> from django.db.models import Avg, Max, Min, Sum, Count >>> User.objects.all().aggregate(Avg('id')) From 1cd4c7f29c586a1fcc3bd05639f2f790803c63e9 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 04:03:37 +0900 Subject: [PATCH 048/100] random --- docs/random.rst | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/docs/random.rst b/docs/random.rst index 37f7d62..6453a13 100644 --- a/docs/random.rst +++ b/docs/random.rst @@ -1,7 +1,7 @@ -How to efficiently select a random object from a model? -======================================================================== +모델에서 무작위 항목을 구하는 효율적인 방법이 있을까요? +============================================================================================ -Your :code:`category` models is like this. +:code:`Category` 모델을 아래와 같이 정의했다고 합시다. .. code-block:: python @@ -15,16 +15,16 @@ Your :code:`category` models is like this. return self.name -You want to get a random Category. We will look at few alternate ways to do this. +저장된 Category 항목 가운데 하나를 무작위로 구해야 합니다. 두 가지 방법을 살펴보겠습니다. -The most straightforward way, you can :code:`order_by` random and fetch the first record. It would look something like this. +먼저 살펴볼 방법은 정직하고 이해하기 쉽습니다. :code:`order_by` 메서드로 항목들을 정렬할 때, 정렬 기준을 '무작위'로 지정하는 것입니다. 데이터를 무작위로 정렬하여 첫 번째 항목을 가져오면 무작위 항목을 구할 수 있습니다. 코드로 작성해 봅시다. .. code-block:: python def get_random(): return Category.objects.order_by("?").first() -Note: :code:`order_by('?')` queries may be expensive and slow, depending on the database backend you’re using. To test other methods, we need to insert one million records in :code:`Category` table. Go to your db like with :code:`python manage.py dbshell` and run this. +주의: 사용하는 데이터베이스 시스템에 따라 :code:`order_by('?')`의 실행 비용이 비싸고 성능이 느릴 수 있습니다. 뒤이어 살펴볼 다른 방법과의 비교를 위해 :code:`Category` 표에 1백만 개의 항목을 추가해 두겠습니다. 명령행 인터페이스에서 :code:`python manage.py dbshell`를 실행하여 데이터베이스 셸을 열고, 아래 질의문을 실행하시면 실습에 필요한 항목을 준비할 수 있습니다. .. code-block:: sql @@ -33,10 +33,9 @@ Note: :code:`order_by('?')` queries may be expensive and slow, depending on the (SELECT Md5(Random() :: text) AS descr FROM generate_series(1, 1000000)); -You don't need to understand the full details of the sql above, it creates one million numbers and :code:`md5-s` them to generate the name, then inserts it in the DB. +위 SQL 질의문을 자세히 이해할 필요는 없습니다. (1부터 1백만까지의 수열을 생성하고 난수에 MD5 해시를 적용한 값을 생성하여 데이터베이스에 저장합니다.) -Now, instead of sorting the whole table, you can get the max id, -generate a random number in range [1, max_id], and filter that. You are assuming that there have been no deletions. +두 번째 방법은 전체 표를 정렬하는 대신 저장된 항목의 마지막 ID를 이용하는 것입니다. 표에서 ID의 최대값을 구하고, 1과 마지막 ID 사이의 난수를 하나 생성합니다. ID가 이 난수와 동일한 항목을 구하면 됩니다. .. code-block:: python @@ -58,7 +57,7 @@ generate a random number in range [1, max_id], and filter that. You are assuming In [6]: get_random2() Out[6]: -If your models has deletions, you can slightly modify the functions, to loop until you get a valid :code:`Category`. +이 방법은 항목을 삭제하거나 해서 ID가 중간에 비어있는 경우에는 쓸 수 없습니다. 그런 경우에는 유효한 값이 나올 때까지 반복하도록 하면 됩니다. 다음은 그 방식으로 위의 함수를 수정한 것입니다. .. code-block:: python @@ -77,7 +76,7 @@ If your models has deletions, you can slightly modify the functions, to loop unt In [10]: get_random3() Out[10]: -Unless your model has a lot of deletions, the :code:`while True:` loop return quickly. Lets use :code:`timeit` to see the differences. +삭제된 항목이 많지 않다면 위의 무한반복 구문 :code:`while True:`은 금방 종료될 것입니다. 그러면 파이썬의 :code:`timeit`을 이용해 두 방법의 성능 차이를 확인해 봅시다. .. code-block:: python @@ -87,6 +86,5 @@ Unless your model has a lot of deletions, the :code:`while True:` loop return qu In [15]: timeit.timeit(get_random, number=100) Out[15]: 56.92513192095794 -:code:`get_random3` is about 283 time faster than :code:`get_random`. :code:`get_random` is the most generic way, but the technique in :code:`get_random3` will work unless you change changed the default way Django generates the id - autoincrementing integers, or there have been too many deletions. - +:code:`get_random3`이 :code:`get_random`보다 283배 빠르게 실행되었습니다. 단, :code:`get_random`은 언제나 이용할 수 있는 반면에, :code:`get_random3`의 방법은 장고의 기본 ID 생성 방식(자동 증가 정수 방식)을 재정의한 경우나 삭제된 항목이 너무 많을 때에는 사용하기가 어려울 수 있습니다. From d8e2fe61cb7fc9511bccdb71a7f65eadbc042d46 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 04:15:51 +0900 Subject: [PATCH 049/100] func_expressions --- docs/func_expressions.rst | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/docs/func_expressions.rst b/docs/func_expressions.rst index dcf4ae0..20ced42 100644 --- a/docs/func_expressions.rst +++ b/docs/func_expressions.rst @@ -1,14 +1,13 @@ -How to use arbitrary database functions in querysets? -======================================================================== +장고가 지원하지 않는 데이터베이스 함수를 사용할 수 있나요? +========================================================================== -Django comes with functions like :code:`Lower`, :code:`Coalesce` and :code:`Max`, but it can't support all database functions, expecially ones which are database specific. +장고에는 :code:`Lower`, :code:`Coalesce`, :code:`Max` 등의 데이터베이스 함수가 포함되어 있습니다. 하지만 장고가 데이터베이스가 지원하는 모든 함수를 제공하는 것은 아닙니다. 특히, 특정 데이터베이스 시스템의 전용 함수들은 제공되지 않습니다. -Django provides :code:`Func` which allows using arbitrary database functions, even if Django doesn't provide them. +장고가 제공하지 않는 데이터베이스 함수를 실행하기 위해서는 장고의 :code:`Func` 객체를 사용하면 됩니다. +PostgreSQL에는 :code:`fuzzystrmatch` 확장 기능이 있습니다. 이 확장에는 텍스트 데이터의 유사도를 측정하기 위한 함수가 여러 가지 포함되어 있습니다. PostgreSQL 데이터베이스 셸에서 :code:`create extension fuzzystrmatch`를 실행하여 이 확장을 설치하고 아래의 실습을 진행해 주세요. -Postgres has :code:`fuzzystrmatch`, which provides several functions to determine similarities. Install the extension in your postgres DB with :code:`create extension fuzzystrmatch` - -We will use the :code:`levenshtein` function. Lets first create some Hero objects. +레벤슈타인 치환 거리 알고리즘을 구현한 :code:`levenshtein` 함수를 이용해 보겠습니다. 실습에 사용할 Hero 모델의 항목을 여러 개 생성합시다. .. code-block:: python @@ -18,7 +17,7 @@ We will use the :code:`levenshtein` function. Lets first create some Hero object Hero.objects.create(name="Xeus", description="A greek God", benevolence_factor=80, category_id=12, origin_id=1) Hero.objects.create(name="Poseidon", description="A greek God", benevolence_factor=80, category_id=12, origin_id=1) -We want to find out the :code:`Hero` objects which have :code:`name` similar to Zeus. You can do +이제 :code:`name`이 'Zeus'와 비슷한 :code:`Hero` 항목들을 구해 봅시다. .. code-block:: python @@ -26,7 +25,7 @@ We want to find out the :code:`Hero` objects which have :code:`name` similar to Hero.objects.annotate(like_zeus=Func(F('name'), function='levenshtein', template="%(function)s(%(expressions)s, 'Zeus')")) -The :code:`like_zeus=Func(F('name'), function='levenshtein', template="%(function)s(%(expressions)s, 'Zeus')")` took two arguments which allowed the database representation, viz, :code:`function` and :code:`template`. If you need to reuse the function, you can define a class like this. +:code:`like_zeus=Func(F('name'), function='levenshtein', template="%(function)s(%(expressions)s, 'Zeus')")` 코드에서 :code:`Func` 객체를 세 개의 인자로 초기화하였습니다. 첫 번째 인자는 함수에 적용할 열, 두 번째 인자는 데이터베이스에서 실행할 함수의 이름, 세 번째 인자는 함수를 실행할 SQL 질의문의 템플릿입니다. 이 함수를 여러 번 재사용할 계획이라면 다음과 같이 클래스를 확장하여 정의해 두면 편리합니다. .. code-block:: python @@ -34,9 +33,9 @@ The :code:`like_zeus=Func(F('name'), function='levenshtein', template="%(functio function='levenshtein' template="%(function)s(%(expressions)s, 'Zeus')" -And then use :code:`Hero.objects.annotate(like_zeus=LevenshteinLikeZeus(F("name")))` +이제 :code:`Hero.objects.annotate(like_zeus=LevenshteinLikeZeus(F("name")))`와 같이 클래스를 이용할 수 있습니다. -You can then filter on this annotated field like this. +이렇게 구한 편집 거리 유사도 필드를 기준으로 항목을 선별할 수 있습니다. .. code-block:: ipython From 74f46ea90906cfe0eeaca533c1252c6335bd95b8 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 04:45:24 +0900 Subject: [PATCH 050/100] =?UTF-8?q?2=EB=B6=80=EA=B9=8C=EC=A7=80=20?= =?UTF-8?q?=ED=87=B4=EA=B3=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/and_query.rst | 2 +- docs/f_query.rst | 8 ++++---- docs/filefield.rst | 2 +- docs/index.rst | 22 +++++++++++----------- docs/introduction.rst | 6 +++--- docs/or_query.rst | 2 +- docs/query.rst | 4 ++-- docs/select_some_fields.rst | 8 ++++---- docs/subquery.rst | 4 ++-- docs/union.rst | 2 +- 10 files changed, 30 insertions(+), 30 deletions(-) diff --git a/docs/and_query.rst b/docs/and_query.rst index 4e7bf8d..ed297e6 100644 --- a/docs/and_query.rst +++ b/docs/and_query.rst @@ -1,4 +1,4 @@ -AND 연산으로 여러 조건을 모두 만족하는 행을 구하려면 어떻게 하나요? +AND 연산으로 여러 조건을 모두 만족하는 항목을 구하려면 어떻게 하나요? +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .. image:: usertable.png diff --git a/docs/f_query.rst b/docs/f_query.rst index d00507c..445afc7 100644 --- a/docs/f_query.rst +++ b/docs/f_query.rst @@ -1,10 +1,10 @@ -필드의 값을 서로 비교하여 행을 선택하려면 어떻게 하나요? +열의 값을 서로 비교하여 항목을 선택할 수 있나요? ============================================================================== -장고 ORM에서 특정한 값을 기준으로 행을 선택하는 것은 간단합니다. 예를 들어, :code:`first_name`이 :code:`'R'`로 시작하는 :code:`User` 모델의 행을 구하려면 +장고 ORM에서 특정한 값을 기준으로 행을 선택하는 것은 간단합니다. 예를 들어, 이름(:code:`first_name`)이 :code:`'R'`로 시작하는 :code:`User` 모델의 행을 구하려면 :code:`User.objects.filter(first_name__startswith='R')`와 같이 코드를 작성하면 됩니다. -그런데 first_name을 last_name과 비교하여 선택하려면 어떻게 해야 할까요? 이럴 때 :code:`F` 객체를 사용합니다. +그런데 이름(:code:`first_name`)을 성(:code:`last_name`)과 비교하여 선택하려면 어떻게 해야 할까요? 이럴 때 :code:`F` 객체를 사용합니다. 실습을 위해 User 행을 몇 개 생성합시다. @@ -35,5 +35,5 @@ In [46]: User.objects.annotate(first=Substr("first_name", 1, 1), last=Substr("last_name", 1, 1)).filter(first=F("last")) Out[46]: , ]> -:code:`F` 객체에 :code:`__gt`, :code:`__lt` 등의 식을 적용하는 것 또한 가능합니다. +:code:`F` 객체에 :code:`__gt`, :code:`__lt` 등의 룩업(lookup)을 적용하는 것 또한 가능합니다. diff --git a/docs/filefield.rst b/docs/filefield.rst index 3a68b9f..41f0d07 100644 --- a/docs/filefield.rst +++ b/docs/filefield.rst @@ -1,4 +1,4 @@ -FileField에 파일이 들어있지 않은 행을 구하려면 어떻게 하나요? +FileField에 파일이 들어있지 않은 행은 어떻게 구할 수 있나요? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 장고의 :code:`FileField`와 :code:`ImageField`는 파일과 이미지 파일의 경로를 저장합니다. 이것은 응용 수준에서의 구별이고, 데이터베이스 수준에서는 모두 :code:`CharField`와 동일한 방식으로 저장됩니다. 파일이 없는 행을 구하려면 다음 코드를 실행하면 됩니다. diff --git a/docs/index.rst b/docs/index.rst index 5ebc2f0..6d32e97 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -2,7 +2,7 @@ +++++++++++++++++++++++ -『장고 ORM 요리책(Django ORM Cookbook)』은 장고의 ORM과 모델을 이용한 다양한 레시피(조리법)를 담은 책입니다. 장고는 모델-템플릿-뷰(MTV) 프레임워크입니다. 이 책에서는 그 가운데 '모델'에 대해 상세히 다룹니다. +『장고 ORM 요리책(Django ORM Cookbook)』은 장고의 ORM(객체 관계 매핑) 기능과 모델 기능을 활용하는 다양한 레시피(조리법)를 담은 책입니다. 장고는 모델-템플릿-뷰(MTV) 프레임워크입니다. 이 책은 그 가운데 '모델'에 대해 상세히 다룹니다. 이 책은 "장고 ORM/쿼리셋/모델으로 ~을 하는 방법은 무엇인가요?"와 같은 질문 50여 개와 그 답을 담고 있습니다. @@ -15,8 +15,8 @@ introduction -정보를 질의하고 걸러내기 -======================== +정보를 조회하고 필요한 항목을 선별하는 방법 +=============================================================== .. toctree:: :maxdepth: 1 @@ -41,8 +41,8 @@ func_expressions -정보를 생성/갱신/삭제하기 -======================= +항목을 생성·갱신·삭제하는 방법 +=================================================================== .. toctree:: :maxdepth: 1 @@ -57,8 +57,8 @@ datetime -질의 결과를 정렬하기 -======================== +질의 결과를 정렬하는 방법 +================================================================ .. toctree:: :maxdepth: 1 @@ -71,8 +71,8 @@ order_by_annotated_field -데이터베이스 모델 짜기 -============================================== +데이터베이스 모델을 설계하는 방법 +=============================================================== .. toctree:: :maxdepth: 1 @@ -95,7 +95,7 @@ -테스트하기 +장고 ORM 코드를 테스트하는 방법 =============================================== .. toctree:: :maxdepth: 1 @@ -108,7 +108,7 @@ 찾아보기 / 표 -================== +=============================== * :ref:`genindex` * :ref:`modindex` diff --git a/docs/introduction.rst b/docs/introduction.rst index 0a469be..db8c9de 100644 --- a/docs/introduction.rst +++ b/docs/introduction.rst @@ -1,7 +1,7 @@ -개요 ------------------ +이 책의 소개 +-------------------------- -장고 ORM은 장고의 핵심 구성요소 가운데 하나로, 우리가 데이터베이스 시스템을 직접 다루지 않고도 데이터베이스를 활용할 수 있도록 편리하고도 강력한 인터페이스를 제공합니다. 장고 ORM은 "간단한 것을 쉽게, 어려운 것도 할 수 있게" 해 줍니다. +장고 ORM은 장고의 핵심 구성요소 가운데 하나로, 장고 ORM은 데이터베이스 시스템을 직접 다루지 않고도 데이터베이스를 활용할 수 있도록 하는 편리하고도 강력한 인터페이스입니다. "간단한 것을 쉽게, 어려운 것을 가능하게" 해 주는 고마운 기능이죠. 이 책은 여러 가지 예제로 문제 상황을 직접 다뤄보며 장고 ORM을 익히도록 합니다. 여러분의 장고 ORM의 이해도를 높여 줄 50여 개의 질문을 준비했습니다. diff --git a/docs/or_query.rst b/docs/or_query.rst index 149df59..8f4c8ff 100644 --- a/docs/or_query.rst +++ b/docs/or_query.rst @@ -1,4 +1,4 @@ -OR 연산으로 일부 조건을 하나라도 만족하는 행을 구하려면 어떻게 하나요? +OR 연산으로 일부 조건을 하나라도 만족하는 항목을 구하려면 어떻게 하나요? +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .. image:: usertable.png diff --git a/docs/query.rst b/docs/query.rst index 58ee7b8..7ce103b 100644 --- a/docs/query.rst +++ b/docs/query.rst @@ -1,5 +1,5 @@ -쿼리셋에 의해 실행되는 SQL 질의문을 확인하고 싶어요 -++++++++++++++++++++++++++++++++++++++++++++++ +장고 ORM이 실행하는 실제 SQL 질의문을 확인할 수 있나요? +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 장고 ORM이 실행하는 질의문 또는 우리가 작성한 코드에 대응하는 SQL 질의문이 무엇인지 확인하고 싶을 때가 있습니다. 확인하는 방법은 매우 직관적인데요, SQL 질의문을 구하고 싶은 :code:`queryset.query`의 :code:`str`을 확인하면 됩니다. diff --git a/docs/select_some_fields.rst b/docs/select_some_fields.rst index 76ac09c..1d08f3e 100644 --- a/docs/select_some_fields.rst +++ b/docs/select_some_fields.rst @@ -1,16 +1,16 @@ -쿼리셋의 일부 필드만 조회하려면 어떻게 하나요? -+++++++++++++++++++++++++++++++++++++++++++++++++++++ +필요한 열만 골라 조회하려면 어떻게 하나요? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .. image:: usertable.png -:code:`auth_user` 모델에는 여러 개의 필드가 들어 있습니다. 그런데 이 필드가 전부 다 필요하지 않을 때도 있죠. 그럴 떄 필요한 필드만 읽어오는 방법을 알아 봅시다. +:code:`auth_user` 모델에는 여러 개의 필드가 정의되어 있습니다. 그런데 이 필드가 전부 다 필요하지 않을 때도 있죠. 그럴 때 필요한 열만을 데이터베이스에서 읽어오는 방법을 알아 봅시다. 장고는 두 가지 방법을 제공합니다. - 쿼리셋의 `values` 메서드와 `values_list` 메서드 - `only` 메서드 -이름이 R로 시작하는 모든 사용자의 :code:`first_name`과 :code:`last_name`을 구해 봅시다. 데이터베이스 시스템의 부하를 줄이기 위해 그 외의 필드는 가져오지 않겠습니다. +이름이 R로 시작하는 모든 사용자의 이름(:code:`first_name`)과 성(:code:`last_name`)을 구해 봅시다. 데이터베이스 시스템의 부하를 줄이기 위해 그 외의 열은 가져오지 않겠습니다. .. code-block:: python diff --git a/docs/subquery.rst b/docs/subquery.rst index 52c12be..3bb3315 100644 --- a/docs/subquery.rst +++ b/docs/subquery.rst @@ -1,7 +1,7 @@ -장고에서 서브쿼리 식을 사용하려면 어떻게 하나요? +장고에서 서브쿼리 식을 사용할 수 있나요? ============================================================== -장고에서 SQL 서브쿼리 식을 사용할 수 있습니다. 간단한 것부터 시작해 봅시다. :code:`auth_user` 모델과 일 대 일(:code:`OneToOne`) 관계로 연결된 :code:`UserParent` 모델이 있다고 합시다. 아래 코드로 :code:`UserParent` 모델에서 :code:`auth_user`를 가진 행을 모두 구할 수 있습니다. +장고에서 SQL 서브쿼리(subquery, 질의문 내의 하위 질의) 식을 사용할 수 있습니다. 간단한 것부터 시작해 봅시다. :code:`auth_user` 모델과 일 대 일(:code:`OneToOne`) 관계로 연결된 :code:`UserParent` 모델이 있다고 합시다. 아래 코드로 :code:`UserParent` 모델에서 :code:`auth_user`를 가진 행을 모두 구할 수 있습니다. .. code-block:: ipython diff --git a/docs/union.rst b/docs/union.rst index 0345fea..a6797ee 100644 --- a/docs/union.rst +++ b/docs/union.rst @@ -1,5 +1,5 @@ 동일한 모델 또는 서로 다른 모델에서 구한 쿼리셋들의 합집합을 구하는 방법은 무엇인가요? -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ SQL에서는 여러 개의 결과 집합을 합할 때 UNION 연산을 이용합니다. 장고 ORM에서 union 메서드를 이용해 쿼리셋을 합할 수 있습니다. 합하려는 쿼리셋의 모델이 서로 다른 경우, 각 쿼리셋에 포함된 필드와 데이터 유형이 서로 맞아야 합니다. From 29230687679b8d3d2d3132cac6bcc76f63235c4d Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 05:01:36 +0900 Subject: [PATCH 051/100] introduction --- docs/introduction.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/introduction.rst b/docs/introduction.rst index db8c9de..d394453 100644 --- a/docs/introduction.rst +++ b/docs/introduction.rst @@ -1,7 +1,7 @@ 이 책의 소개 -------------------------- -장고 ORM은 장고의 핵심 구성요소 가운데 하나로, 장고 ORM은 데이터베이스 시스템을 직접 다루지 않고도 데이터베이스를 활용할 수 있도록 하는 편리하고도 강력한 인터페이스입니다. "간단한 것을 쉽게, 어려운 것을 가능하게" 해 주는 고마운 기능이죠. +장고 ORM은 장고의 핵심 구성요소 가운데 하나로, 데이터베이스 시스템을 직접 다루지 않고도 데이터베이스를 활용할 수 있도록 하는 편리하고도 강력한 인터페이스입니다. "간단한 것을 쉽게, 어려운 것을 가능하게" 해 주는 고마운 기능이죠. 이 책은 여러 가지 예제로 문제 상황을 직접 다뤄보며 장고 ORM을 익히도록 합니다. 여러분의 장고 ORM의 이해도를 높여 줄 50여 개의 질문을 준비했습니다. @@ -9,9 +9,9 @@ 이 책을 읽는 방법 +++++++++++++++++++++++++ -이 책의 각 장은 각각 질문 하나를 나타냅니다. 비슷한 주제를 다루는 질문들은 서로 모아 두었습니다. 이 책을 읽는 방법은 크게 두 가지가 있습니다. +이 책의 각 장은 각각 질문을 하나씩 다룹니다. 비슷한 주제를 다루는 장들은 서로 모아 두었습니다. 이 책을 읽는 방법은 크게 두 가지가 있습니다. 1. 특정한 질문에 관한 답을 찾는다면 그 질문을 다루는 장과 그와 연결된 장을 함께 읽으세요. -2. 장고 ORM와 모델 계층에 대한 이해도를 높이고 싶다면 책을 처음부터 차례대로 읽으세요. +2. 장고 ORM과 모델 계층에 대한 이해도를 높이고 싶다면 책을 처음부터 차례대로 읽으세요. From 6ed7cc8815216fe48b802b2db0e28f7c261cb0c0 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 05:07:14 +0900 Subject: [PATCH 052/100] =?UTF-8?q?=EC=98=A4=ED=83=80,=20=EB=AC=B8?= =?UTF-8?q?=EA=B5=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- docs/and_query.rst | 2 +- docs/notequal_query.rst | 4 ++-- docs/or_query.rst | 2 +- docs/query.rst | 2 +- docs/random.rst | 2 +- docs/union.rst | 4 ++-- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 25b4222..5c066a9 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,12 @@ 이 책에서는 전체 주제 공통으로 아래에서 설명하는 데이터 모델을 이용합니다. -### 모델 +### 실습용 모델 준비 -여러분은 장고를 이용하여 UMSRA의 연구원들이 사용할 모델과 관리자 뷰(admin)를 제작하는 중입니다. 여러분은 프로젝트를 개체를 나타내는 `entities` 앱과 사건을 나타내는 `events` 앱 두 개로 나누어 작성하게 되었습니다. 그리고 각 앱의 모델을 다음과 같이 준비했습니다. (지금 자세히 보지 않아도 됩니다. 책을 보다가 필요하실 떄 참고해주세요.) +여러분은 장고를 이용하여 UMSRA의 연구원들이 사용할 모델과 관리자 뷰(admin)를 제작하는 중입니다. 여러분은 프로젝트를 개체를 나타내는 `entities` 앱과 사건을 나타내는 `events` 앱 두 개로 나누어 작성하게 되었습니다. 그리고 각 앱의 모델을 다음과 같이 준비했습니다. (지금 자세히 보지 않아도 됩니다. 책을 보다가 필요할 때 참고해주세요.) -#### events 앱의 모델 +#### Events 앱의 모델 from django.db import models diff --git a/docs/and_query.rst b/docs/and_query.rst index ed297e6..925567c 100644 --- a/docs/and_query.rst +++ b/docs/and_query.rst @@ -17,7 +17,7 @@ AND 연산으로 여러 조건을 모두 만족하는 항목을 구하려면 어 질의문 살펴보기 ----------------------- -위 조건의 SQL 질의문은 다음과 같은 형태입니다. +위 조건의 SQL 질의문은 다음과 같이 생성됩니다. :: .. code-block:: sql diff --git a/docs/notequal_query.rst b/docs/notequal_query.rst index 55b3784..8223c2f 100644 --- a/docs/notequal_query.rst +++ b/docs/notequal_query.rst @@ -5,7 +5,7 @@ NOT 연산으로 조건을 부정하려면 어떻게 하나요? 장고의 사용자 계정 관리 앱인 :code:`django.contrib.auth`를 사용하면 데이터베이스에 :code:`auth_user`이라는 표가 생성됩니다. 이 표에는 :code:`username`, :code:`first_name`, :code:`last_name` 등의 열이 있습니다. -id < 5 라는 조건을 만족하지 않는 모든 사용자를 구하려 한다고 해 봅시다. 이를 수행하려면 NOT 연산이 필요합니다. +id < 5 라는 조건을 만족하지 않는 모든 사용자를 구해 봅시다. 이를 수행하려면 NOT 연산이 필요합니다. 장고에서는 다음 두 방법으로 구할 수 있습니다. @@ -16,7 +16,7 @@ id < 5 라는 조건을 만족하지 않는 모든 사용자를 구하려 한다 질의문 살펴보기 ----------------------- -위 조건의 SQL 질의문은 대략 다음과 같습니다. :: +위 조건의 SQL 질의문은 다음과 같이 생성됩니다. :: SELECT id, username, first_name, last_name, email FROM auth_user WHERE NOT id < 5; diff --git a/docs/or_query.rst b/docs/or_query.rst index 8f4c8ff..0c8cfc5 100644 --- a/docs/or_query.rst +++ b/docs/or_query.rst @@ -16,7 +16,7 @@ OR 연산으로 일부 조건을 하나라도 만족하는 항목을 구하려 질의문 살펴보기 ----------------------- -위 조건의 SQL 질의문은 대략 다음과 같습니다. :: +위 조건의 SQL 질의문은 다음과 같이 생성됩니다. :: SELECT username, first_name, last_name, email FROM auth_user WHERE first_name LIKE 'R%' OR last_name LIKE 'D%'; diff --git a/docs/query.rst b/docs/query.rst index 7ce103b..b512df5 100644 --- a/docs/query.rst +++ b/docs/query.rst @@ -1,7 +1,7 @@ 장고 ORM이 실행하는 실제 SQL 질의문을 확인할 수 있나요? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -장고 ORM이 실행하는 질의문 또는 우리가 작성한 코드에 대응하는 SQL 질의문이 무엇인지 확인하고 싶을 때가 있습니다. 확인하는 방법은 매우 직관적인데요, SQL 질의문을 구하고 싶은 :code:`queryset.query`의 :code:`str`을 확인하면 됩니다. +장고 ORM이 실행하는 질의문 또는 우리가 작성한 코드에 대응하는 SQL 질의문이 무엇인지 확인하고 싶을 때가 있습니다. SQL 질의문을 구하고 싶은 :code:`queryset.query`의 :code:`str`을 확인하면 됩니다. 간단하죠? :code:`Event`라는 모델이 있을 때, 이 모델의 모든 행을 데이터베이스에서 읽어오려면 :code:`Event.objects.all()`과 같은 코드를 작성하면 됩니다. 이렇게 구한 쿼리셋의 :code:`str(queryset.query)`를 확인하여 SQL 질의문을 살펴봅시다. diff --git a/docs/random.rst b/docs/random.rst index 460ebd2..a5d54ce 100644 --- a/docs/random.rst +++ b/docs/random.rst @@ -1,4 +1,4 @@ -무작위 항목을 효율적으로 뽑는 방법이 있을까요? +항목을 무작위로 뽑고 싶습니다. 효율적인 방법이 있을까요? ============================================================================================ :code:`Category` 모델을 아래와 같이 정의했다고 합시다. diff --git a/docs/union.rst b/docs/union.rst index a6797ee..f0d672a 100644 --- a/docs/union.rst +++ b/docs/union.rst @@ -1,4 +1,4 @@ -동일한 모델 또는 서로 다른 모델에서 구한 쿼리셋들의 합집합을 구하는 방법은 무엇인가요? +동일한 모델 또는 서로 다른 모델에서 구한 쿼리셋들을 합할 수 있나요? +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ SQL에서는 여러 개의 결과 집합을 합할 때 UNION 연산을 이용합니다. 장고 ORM에서 union 메서드를 이용해 쿼리셋을 합할 수 있습니다. 합하려는 쿼리셋의 모델이 서로 다른 경우, 각 쿼리셋에 포함된 필드와 데이터 유형이 서로 맞아야 합니다. @@ -43,5 +43,5 @@ union 메서드는 합하려는 쿼리셋의 필드와 데이터 유형이 서 "name", "gender" )) -위 코드를 실행하면 :code:`Hero` 모델과 :code:`Villain` 모델의 이름과 성별을 함꼐 구할 수 있습니다. +위 코드를 실행하면 :code:`Hero` 모델과 :code:`Villain` 모델의 이름과 성별을 구할 수 있습니다. From d071946bb9d88de1dabb45ec33bbbda2957504f0 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 05:35:11 +0900 Subject: [PATCH 053/100] singleton --- docs/copy.rst | 6 +++--- docs/multiple_objects.rst | 12 ++++++------ docs/singleton.rst | 10 +++++----- docs/update_denormalized_fields.rst | 25 ++++++++++++------------- 4 files changed, 26 insertions(+), 27 deletions(-) diff --git a/docs/copy.rst b/docs/copy.rst index f643c06..ec42f85 100644 --- a/docs/copy.rst +++ b/docs/copy.rst @@ -1,9 +1,9 @@ -How to copy or clone an existing model object? +기존에 저장된 행을 복사해 저장하는 방법은 무엇인가요? ======================================================================== -There is no built-in method for copying model instances, it is possible to create new instance with all fields values copied. +장고 ORM에는 모델 인스턴스를 복사하는 내장 메서드가 없습니다. 하지만 모든 필드의 값을 복사하여 새 인스턴스를 만들고 새로 저장하는 것은 어렵지 않습니다. -If an instance is saved with instance's :code:`pk` set to :code:`None`, the instance is used to create a new record in the DB. That means every field other than the :code:`PK` is copied. +모델 인스턴스를 저장할 때, :code:`pk` 필드 값을 :code:`None`으로 지정해두면 데이터베이스에 신규 행으로 기록됩니다. :code:`pk` 열 외의 모든 필드 값은 그대로 복제됩니다. .. code-block:: ipython diff --git a/docs/multiple_objects.rst b/docs/multiple_objects.rst index 2158675..ecaad01 100644 --- a/docs/multiple_objects.rst +++ b/docs/multiple_objects.rst @@ -1,10 +1,10 @@ -How to create multiple objects in one shot? -++++++++++++++++++++++++++++++++++++++++++++++++++ +여러 개의 행을 한번에 생성하는 방법이 있나요? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -There are conditions when we want to save multiple objects in one go. Say we want to add multiple categories at once and we don't want to make many queries to the database. -We can use :code:`bulk_create` for creating multiple objects in one shot. +여러 개의 신규 객체를 한꺼번에 저장하고 싶은 경우가 있습니다. 예를 들어, 여러 개의 분류 항목을 단번에 생성하되, 데이터베이스에 질의를 여러 번 수행하지 않아야 한다고 합시다. +:code:`bulk_create` 메서드를 이용하면 여러 개의 신규 객체를 한 번에 저장할 수 있습니다. -Here is an example. +다음 예를 살펴보세요. .. code-block:: ipython @@ -19,4 +19,4 @@ Here is an example. >>> Category.objects.all().count() 5 -:code:`bulk_create` takes a list of unsaved objects. +:code:`bulk_create` 메서드는 저장되지 않은 객체들을 담은 리스트를 인자로 전달받습니다. diff --git a/docs/singleton.rst b/docs/singleton.rst index c852a04..827d4e1 100644 --- a/docs/singleton.rst +++ b/docs/singleton.rst @@ -1,9 +1,9 @@ -How to ensure that only one object can be created? -======================================================================== +특정 모델의 항목이 하나만 생성되도록 강제하는 방법이 있나요? +============================================================================ -Sometimes you want to ensure that only one record can be created for a model. This is commonly required as application configuration store, or as a locking mechanism to access shared resources. +특정 모델의 항목이 단 하나만 생성되도록 강제하고 싶을 때가 있습니다. 프로그램의 환경 설정 기록, 공유 자원에 대한 잠금 제어 등을 예로 들 수 있습니다. -Let us convert our :code:`Origin` model to be singleton. +다음은 :code:`Origin`이라는 모델을 싱글턴(단일개체)으로 만드는 기법입니다. .. code-block:: python @@ -15,4 +15,4 @@ Let us convert our :code:`Origin` model to be singleton. self.pk = self.__class__.objects.first().pk super().save(*args, **kwargs) -What did we do? We overrode the :code:`save` method, and set the :code:`pk` to an existing value. This ensures that when :code:`create` is called and any object exists, an :code:`IntegrityError` is raised. +위 코드는 :code:`save` 메서드를 재정의하여 :code:`pk` 필드를 이미 존재하는 값으로 지정하도록 강제합니다. 이로써 객체가 이미 존재할 때 :code:`create` 메서드를 호출하는 경우 :code:`IntegrityError` 예외가 발생하도록 합니다. diff --git a/docs/update_denormalized_fields.rst b/docs/update_denormalized_fields.rst index 33c1564..f382a24 100644 --- a/docs/update_denormalized_fields.rst +++ b/docs/update_denormalized_fields.rst @@ -1,7 +1,7 @@ -How to update denormalized fields in other models on save? -======================================================================== +모델 인스턴스를 저장할 때, 다른 모델에 반정규화된 필드를 함께 갱신하는 방법이 있나요? +========================================================================================================== -You have models like this. +모델을 다음과 같이 구성했다고 합시다. .. code-block:: python @@ -26,9 +26,9 @@ You have models like this. # ... -You need the :code:`hero_count` and :code:`villain_count`, to be updated when new objects are created. +Hero 모델과 Villain 모델의 항목을 새로 저장할 때, Category 모델의 :code:`hero_count` 필드와 :code:`villain_count` 필드를 갱신해야 합니다. -You can do something like this +다음과 같이 Hero 모델과 Villain 모델의 :code:`save` 메서드를 재정의하면 됩니다. .. code-block:: python @@ -50,9 +50,9 @@ You can do something like this super().save(*args, **kwargs) -Note how we did not use :code:`self.category.hero_count += 1`, as :code:`update` will do a DB update. +위 코드에서 :code:`self.category.hero_count += 1`과 같이 인스턴스의 값을 수정하는 것이 아니라, :code:`update` 메서드로 데이터베이스의 갱신을 수행하도록 한 것을 확인하시기 바랍니다. -The alternative method is using `signals`. You can do it like this. +또 다른 방법으로, '시그널'이라는 기능을 이용하는 방법이 있습니다. 시그널을 이용하는 예를 살펴봅시다. .. code-block:: python @@ -72,12 +72,11 @@ The alternative method is using `signals`. You can do it like this. Category.objects.filter(pk=villain.category_id).update(villain_count=F('villain_count')+1) -Signals vs Overriding :code:`.save` -++++++++++++++++++++++++++++++++++++ +:code:`save` 메서드 재정의 방법과 시그널의 비교 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +:code:`save` 메서드를 재정의하는 방법과 시그널을 이용하는 방법 모두 사용할 수 있습니다. 어느 것을 사용하는 것이 좋을까요? 다음 규칙을 권해 드립니다. -Since either of signals of :code:`.save` can be used for the save behviour, when should you use which one? I follow a simple rule. - -- If your fields depend on a model you control, override :code:`.save` -- If your fields depend on a model from a 3rd party app, which you do no control, use signals. +- 반정규화 필드에 영향을 끼치는 모델을 여러분이 통제할 수 있다면 `save` 메서드를 재정의합니다. +- 반정규화 필드에 영향을 끼치는 모델을 여러분이 통제할 수 없다면(그 영향이 라이브러리 등에서 이루어진다면) 시그널을 이용합니다. From b2bc04d6f21a4465961a23cb6159114d8d6b1cd0 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 05:41:35 +0900 Subject: [PATCH 054/100] truncate --- docs/truncate.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/truncate.rst b/docs/truncate.rst index 275c4b4..81a1db8 100644 --- a/docs/truncate.rst +++ b/docs/truncate.rst @@ -1,9 +1,9 @@ -How to perform truncate like operation using Django ORM? -========================================================== +TRUNCATE 문을 수행하는 방법이 있나요? +============================================================= -Truncate statement in SQL is meant to empty a table for future use. -Though Django doesn't provide a builtin to truncate a table, but still similar result can be achived using :code:`delete()` method. -For example: +SQL의 TRUNCATE 문은 표에 저장된 모든 항목을 제거하는 명령입니다. 장고는 TRUNCATE 문을 실행하는 명령을 제공되지 않습니다. 하지만 :code:`delete` 메서드를 이용해 비슷한 결과를 얻을 수 있습니다. + +다음 예를 보십시오. .. code-block:: python @@ -14,7 +14,7 @@ For example: >>> Category.objects.all().count() 0 -This works, but this uses :code:`DELETE FROM ...` SQL statement. If you have a large number of records, this can be quite slow. You can add a :code:`classmethod` to :code:`Category` if you want to enable :code:`truncate`. +위 코드는 잘 동작합니다. 하지만 TRUNCATE 문이 아니라 :code:`DELETE FROM ...`과 같은 SQL 질의를 수행합니다. 삭제해야 하는 항목의 수가 매우 많은 경우 처리 속도가 느릴 수 있습니다. :code:`truncate` 명령이 필요하다면 다음과 같이 :code:`Category` 모델에 :code:`classmethod`로 추가하면 됩니다. .. code-block:: python @@ -27,4 +27,4 @@ This works, but this uses :code:`DELETE FROM ...` SQL statement. If you have a l with connection.cursor() as cursor: cursor.execute('TRUNCATE TABLE "{0}" CASCADE'.format(cls._meta.db_table)) -Then you can call :code:`Category.truncate()` to a real database truncate. +이렇게 메서드를 정의해 두면 :code:`Category.truncate()`를 실행하여 정말로 데이터베이스 시스템에 TRUNCATE 문을 질의할 수 있습니다. From 54ea6bc14073de0ec517fc606944d28cfb9404c9 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 05:51:42 +0900 Subject: [PATCH 055/100] signals --- docs/signals.rst | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/signals.rst b/docs/signals.rst index e30615e..121995e 100644 --- a/docs/signals.rst +++ b/docs/signals.rst @@ -1,7 +1,7 @@ -What signals are raised by Django during object creation or update? -======================================================================== +모델 인스턴스가 생성·갱신될 때 발생하는 시그널에는 어떤 것이 있나요? +==================================================================================== -Django provides signals which allows hooking into a model objects creation and deletion lifecycle. The signals provided by Django are +장고의 시그널을 이용하면 모델 인스턴스의 생명주기에 따라 특정 코드가 실행되도록 예약해 둘 수 있습니다. 장고가 제공하는 시그널의 종류는 다음과 같습니다. - :code:`pre_init` - :code:`post_init` @@ -11,18 +11,18 @@ Django provides signals which allows hooking into a model objects creation and d - :code:`post_delete` -Among these, the most commonly used signals are :code:`pre_save` and :code:`post_save`. We will look into them in detail. +이 가운데 :code:`pre_save`와 :code:`post_save`가 가장 많이 사용됩니다. 이 두 시그널을 좀 더 자세히 살펴봅시다. -Signals vs overriding .save ------------------------------------ +시그널과 :code:`save` 메서드 재정의 비교 +----------------------------------------------------- -Since signals can be used for similar effects as overriding :code:`.save`, which one to use is a frequent source of confusion. Here is when you should use which. +시그널을 이용하면 :code:`save` 메서드를 재정의하는 것과 비슷한 효과를 누릴 수 있습니다. 그래서 어느 것을 사용해야 할지 헷갈릴 수도 있는데요, 다음 규칙에 따르시기 바랍니다. -- If you want other people, eg. third party apps, to override or customize the object :code:`save` behaviour, you should raise your own signals -- If you are hooking into the :code:`save` behavior of an app you do not control, you should hook into the :code:`post_save` or :code:`pre_save` -- If you are customizing the save behaviour of apps you control, you should override :code:`save`. +- 다른 사람(외부 라이브러리 등)이 여러분 앱의 :code:`save` 메서드를 재정의·커스터마이즈하도록 허용하려면 직접 시그널을 발생시켜야 합니다. +- 여러분이 통제할 수 없는 앱의 :code:`save` 메서드에 코드를 예약해야 한다면 :code:`post_save` 시그널 또는 :code:`pre_save` 시그널을 이용해야 합니다. +- 여러분이 통제할 수 있는 앱의 저장 방식을 손 볼 때는 :code:`save` 메서드를 재정의해야 합니다. -Lets take an example of a :code:`UserToken` model. This a class used for providing authentication and should get created whenever a :code:`User` is created. +다음은 :code:`UserToken` 모델의 예입니다. 이 모델은 사용자 인증 정보를 제공하는 역할을 하며, :code:`User`가 생성될 때 함께 생성됩니다. .. code-block:: python From ca47733a1a8760165bfcfd6662fad9b4fb37582b Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 05:56:45 +0900 Subject: [PATCH 056/100] datetime --- docs/datetime.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/datetime.rst b/docs/datetime.rst index fb291fc..3475e4c 100644 --- a/docs/datetime.rst +++ b/docs/datetime.rst @@ -1,8 +1,8 @@ -How to convert string to datetime and store in database? -============================================================ +시간 정보를 다른 양식으로 변환하여 데이터베이스에 저장하려면 어떻게 해야 하나요? +============================================================================================= -We can convert a date-string and store it in the database using django in many ways. Few of them are discussed below. -Lets say we have a date-string as "2018-03-11" we can not directly store it to our date field, so we can use some dateparser or python library for it. :: +장고에서 시간을 나타내는 텍스트를 다른 양식의 텍스트로 변환하여 데이터베이스에 저장하는 방법은 여러 가지가 있습니다. 몇 가지만 소개하겠습니다. +"2018-03-11"이라는 시간 텍스트가 있는데, 이 양식으로는 데이터베이스에 저장할 수 없다고 가정합시다. 아래와 같이 장고의 dateparser 모듈이나 파이썬 표준 라이브러리를 이용하여 날짜 양식을 변환할 수 있습니다. :: >>> user = User.objects.get(id=1) >>> date_str = "2018-03-11" From e0f16010840d43f09a129c4bee2f9dfe89b978ad Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 05:58:53 +0900 Subject: [PATCH 057/100] fix: truncate --- docs/truncate.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/truncate.rst b/docs/truncate.rst index 81a1db8..64989a3 100644 --- a/docs/truncate.rst +++ b/docs/truncate.rst @@ -1,7 +1,7 @@ TRUNCATE 문을 수행하는 방법이 있나요? ============================================================= -SQL의 TRUNCATE 문은 표에 저장된 모든 항목을 제거하는 명령입니다. 장고는 TRUNCATE 문을 실행하는 명령을 제공되지 않습니다. 하지만 :code:`delete` 메서드를 이용해 비슷한 결과를 얻을 수 있습니다. +SQL의 TRUNCATE 문은 표에 저장된 모든 항목을 제거하는 명령입니다. 장고는 TRUNCATE 문을 실행하는 명령을 제공하지 않습니다. 하지만 :code:`delete` 메서드를 이용해 비슷한 결과를 얻을 수 있습니다. 다음 예를 보십시오. From bfb034c2196cee9baac7c36a2856ab2cbc05a8ca Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 18:20:35 +0900 Subject: [PATCH 058/100] =?UTF-8?q?join=20=EC=9B=90=EC=96=B4=20=EB=B3=91?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/join.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/join.rst b/docs/join.rst index f93d3f2..031c8bc 100644 --- a/docs/join.rst +++ b/docs/join.rst @@ -1,4 +1,4 @@ -두 모델을 결합하려면 어떻게 하나요? +두 모델을 결합(JOIN)하려면 어떻게 하나요? ======================================================== SQL에서는 JOIN 문을 이용해 동일한 값을 가진 열을 기준으로 두 표를 결합할 수 있습니다. 결합 연산은 여러 가지 방법으로 수행할 수 있습니다. 다음은 장고에서 이를 수행하는 몇 가지 예입니다. :: From 7c865a798e10bf1e17a783ea77cb1fe2879bb27b Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 18:24:51 +0900 Subject: [PATCH 059/100] =?UTF-8?q?auto=20increment=20=EB=B3=91=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/random.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/random.rst b/docs/random.rst index a5d54ce..ce5bc1a 100644 --- a/docs/random.rst +++ b/docs/random.rst @@ -86,5 +86,5 @@ In [15]: timeit.timeit(get_random, number=100) Out[15]: 56.92513192095794 -:code:`get_random3`이 :code:`get_random`보다 283배 빠르게 실행되었습니다. 단, :code:`get_random`은 언제나 이용할 수 있는 반면에, :code:`get_random3`의 방법은 장고의 기본 ID 생성 방식(자동 증가 정수 방식)을 재정의한 경우나 삭제된 항목이 너무 많을 때에는 사용하기가 어려울 수 있습니다. +:code:`get_random3`이 :code:`get_random`보다 283배 빠르게 실행되었습니다. 단, :code:`get_random`은 언제나 이용할 수 있는 반면에, :code:`get_random3`의 방법은 장고의 기본 ID 생성 방식(auto increment, 자동 증가)을 재정의한 경우나 삭제된 항목이 너무 많을 때에는 사용하기가 어려울 수 있습니다. From 4ee1165ab4887c68707e98a532619eeae0b5632c Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 18:25:51 +0900 Subject: [PATCH 060/100] signals --- docs/signals.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/signals.rst b/docs/signals.rst index 121995e..bbce625 100644 --- a/docs/signals.rst +++ b/docs/signals.rst @@ -19,7 +19,7 @@ 시그널을 이용하면 :code:`save` 메서드를 재정의하는 것과 비슷한 효과를 누릴 수 있습니다. 그래서 어느 것을 사용해야 할지 헷갈릴 수도 있는데요, 다음 규칙에 따르시기 바랍니다. - 다른 사람(외부 라이브러리 등)이 여러분 앱의 :code:`save` 메서드를 재정의·커스터마이즈하도록 허용하려면 직접 시그널을 발생시켜야 합니다. -- 여러분이 통제할 수 없는 앱의 :code:`save` 메서드에 코드를 예약해야 한다면 :code:`post_save` 시그널 또는 :code:`pre_save` 시그널을 이용해야 합니다. +- 여러분이 통제할 수 없는 앱의 :code:`save` 메서드가 호출될 때 원하는 코드가 실행되도록 하려면 :code:`post_save` 시그널 또는 :code:`pre_save` 시그널을 이용해야 합니다. - 여러분이 통제할 수 있는 앱의 저장 방식을 손 볼 때는 :code:`save` 메서드를 재정의해야 합니다. 다음은 :code:`UserToken` 모델의 예입니다. 이 모델은 사용자 인증 정보를 제공하는 역할을 하며, :code:`User`가 생성될 때 함께 생성됩니다. From e2e02d236be1285d13d4d21bd5a21159b40de523 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 18:32:38 +0900 Subject: [PATCH 061/100] copy --- docs/copy.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/copy.rst b/docs/copy.rst index ec42f85..f484d14 100644 --- a/docs/copy.rst +++ b/docs/copy.rst @@ -1,9 +1,9 @@ -기존에 저장된 행을 복사해 저장하는 방법은 무엇인가요? +기존에 저장된 행을 복사해 새로 저장하는 방법은 무엇인가요? ======================================================================== 장고 ORM에는 모델 인스턴스를 복사하는 내장 메서드가 없습니다. 하지만 모든 필드의 값을 복사하여 새 인스턴스를 만들고 새로 저장하는 것은 어렵지 않습니다. -모델 인스턴스를 저장할 때, :code:`pk` 필드 값을 :code:`None`으로 지정해두면 데이터베이스에 신규 행으로 기록됩니다. :code:`pk` 열 외의 모든 필드 값은 그대로 복제됩니다. +모델 인스턴스를 저장할 때, :code:`pk` 필드 값이 :code:`None`으로 지정되어 있으면 데이터베이스에 새 행으로 저장됩니다. :code:`pk` 열 외의 모든 필드 값은 그대로 복제됩니다. .. code-block:: ipython From 382bc9a1bb47a521270c7cd0870f90ac18cc7399 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 18:34:18 +0900 Subject: [PATCH 062/100] distinct --- docs/distinct.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/distinct.rst b/docs/distinct.rst index a4cab81..aee1148 100644 --- a/docs/distinct.rst +++ b/docs/distinct.rst @@ -14,5 +14,5 @@ ).filter(name_count=1) records = User.objects.filter(first_name__in=[item['first_name'] for item in distinct]) -한편, :code:`User.objects.distinct("first_name").all()`와 같은 코드는 고유한 :code:`first_name`을 가진 사용자 중 첫번째 항목을 구하는 코드입니다. 위 코드와는 실행 결과가 다릅니다. +한편, :code:`User.objects.distinct("first_name").all()`와 같은 코드는 고유한 :code:`first_name`을 가진 사용자별로 첫번째 사용자를 구하는 코드입니다. 위 코드와는 실행 결과가 다릅니다. From 7d234ea7a112e849bdbf18d619d85c4097cb07af Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 18:38:50 +0900 Subject: [PATCH 063/100] =?UTF-8?q?=EA=B4=80=EB=8C=80=ED=95=9C=20->=20?= =?UTF-8?q?=EC=84=A0=ED=95=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/subquery.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/subquery.rst b/docs/subquery.rst index 3bb3315..6a7bf0e 100644 --- a/docs/subquery.rst +++ b/docs/subquery.rst @@ -31,7 +31,7 @@ ) -이 모델에서 가장 관대한 영웅을 구하려면 다음 코드를 실행합니다. +이 모델에서 가장 선한 영웅을 구하려면 다음 코드를 실행합니다. .. code-block:: python From 0d66fa4af0516f1c7978b5c16712801c4a9d6ec4 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 18:46:04 +0900 Subject: [PATCH 064/100] asc_or_desc --- docs/asc_or_desc.rst | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/docs/asc_or_desc.rst b/docs/asc_or_desc.rst index 21705ab..f2738fc 100644 --- a/docs/asc_or_desc.rst +++ b/docs/asc_or_desc.rst @@ -1,24 +1,22 @@ -쿼리셋을 어떻게 오름차순 혹은 내림차순으로 정렬할 수 있을까요? -============================================================= +쿼리셋을 오름차순/내림차순으로 정렬할 수 있나요? +====================================================================== -쿼리셋은 :code:`order_by` 메서드를 사용해서 정렬할 수 있습니다. 오름차순 혹은 내림차순으로 정렬하기 위해선 기준이 되는 필드를 전달해야 합니다. -쿼리는 다음과 같습니다. +:code:`order_by` 메서드로 쿼리셋을 정렬할 수 있습니다. 기준 필드를 지정해 오름차순 혹은 내림차순으로 정렬할 수 있습니다. 다음 코드를 살펴보세요. .. code-block:: ipython - >>> User.objects.all().order_by('date_joined') # 오름차순 + >>> User.objects.all().order_by('date_joined') # 오름차순 , , , , , , , , , , , , ]> - >>> User.objects.all().order_by('-date_joined') # 내림차순 + >>> User.objects.all().order_by('-date_joined') # 내림차순 , , , , , , , , , , , , ]> -여러개의 필드를 전달할 수도 있습니다. +기준 필드를 여러 개 지정할 수도 있습니다. .. code-block:: ipython User.objects.all().order_by('date_joined', '-last_login') -SQL은 다음과 같습니다. - +SQL 질의문은 다음과 같습니다. .. code-block:: sql From 6fcf6612c086598aa71f9c2d586302cd5309618e Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 18:53:08 +0900 Subject: [PATCH 065/100] case_insensitive --- docs/case_insensitive.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/case_insensitive.rst b/docs/case_insensitive.rst index 2652518..3a13a8e 100644 --- a/docs/case_insensitive.rst +++ b/docs/case_insensitive.rst @@ -1,16 +1,16 @@ -쿼리셋을 어떻게 대소문자 관계없이 정렬할 수 있을까요? +대문자·소문자를 구별하지 않고 정렬하려면 어떻게 하나요? ============================================================ .. image:: usertable2.png -어떤 문자열들을 :code:`order_by` 를 통해 정렬하려고 할때, 정렬은 알파벳 순서 그리고 알파벳 대소문자를 구분합니다. 예를 들면 다음과 같습니다. +:code:`order_by` 메서드로 쿼리셋을 정렬할 때, 텍스트 필드를 기준으로 하면 알파벳의 대문자·소문자를 구분하여 정렬이 수행됩니다. 다음 예에서 보듯, 대문자에 소문자보다 높은 우선순위가 부여됩니다. .. code-block:: ipython >>> User.objects.all().order_by('username').values_list('username', flat=True) -만약 쿼리셋을 대소문자 구분 없이 문자열을 정렬하고 싶다면 다음과 같이 할 수 있습니다. +텍스트 필드에서 대문자·소문자를 구별하지 않고 정렬하려면 다음과 같이 :code:`Lower`를 사용하면 됩니다. .. code-block:: ipython @@ -18,7 +18,7 @@ >>> User.objects.all().order_by(Lower('username')).values_list('username', flat=True) -또 다른 방법으로는, :code:`Lower` 를 사용하여 Annotate된 필드를 생성하고, 해당 필드를 가지고 정렬 할 수 있습니다. +:code:`annotate` 메서드로 :code:`Lower`를 적용한 열을 준비하고, 그 열을 기준으로 정렬하는 방법도 가능합니다. .. code-block:: python From 1332f03a582cf77e67c2b97fb3ea7c813e1e4cd2 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 19:02:08 +0900 Subject: [PATCH 066/100] order_by_related_model --- docs/order_by_related_model.rst | 14 ++++++++------ docs/order_by_two.rst | 5 +++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/docs/order_by_related_model.rst b/docs/order_by_related_model.rst index f779860..95ac1fa 100644 --- a/docs/order_by_related_model.rst +++ b/docs/order_by_related_model.rst @@ -1,6 +1,7 @@ -어떻게 다른 테이블과 연결된 필드(외래키)를 기준으로 정렬할 수 있을까요? +외래 키로 연결된 다른 표의 열을 기준으로 정렬할 수 있나요? +========================================================================== -:code:`Category` 와 :code:`Hero` 모델 두 개가 있습니다. +:code:`Category` 모델과 :code:`Hero` 모델이 다음과 같이 외래 키로 연결되어 있습니다. .. code-block:: python @@ -13,7 +14,8 @@ name = models.CharField(max_length=100) category = models.ForeignKey(Category, on_delete=models.CASCADE) -먼저 category별로 정렬하고 각 category 내에서 `Hero` 의 name순으로 정렬하려면 이렇게 할 수 있습니다. +아래 코드는 :code:`Hero` 모델의 쿼리셋을 category 필드 순으로 정렬하되, category가 같은 항목은 (:code:`Hero`의) name 필드 순으로 정렬합니다. + .. code-block:: python @@ -21,10 +23,9 @@ 'category__name', 'name' ) -:code:`'category__name'`안에 있는 더블 언더스코어(:code:`__` )를 주의 깊게 살펴보세요. -더블 언더스코어를 사용하면, 연결된 모델의 필드를 기준으로 정렬할 수 있습니다. +:code:`'category__name'` 인자에 이중 밑줄 기호(:code:`__` )를 사용한 것을 봐 주세요. 이중 밑줄 기호로 연결된 모델의 필드를 가리킬 수 있습니다. -SQL을 살펴보겠습니다. +SQL 질의문은 다음과 같이 생성됩니다. .. code-block:: sql @@ -35,3 +36,4 @@ SQL을 살펴보겠습니다. INNER JOIN "entities_category" ON ("entities_hero"."category_id" = "entities_category"."id") ORDER BY "entities_category"."name" ASC, "entities_hero"."name" ASC + diff --git a/docs/order_by_two.rst b/docs/order_by_two.rst index 8fbc8a2..c6af4df 100644 --- a/docs/order_by_two.rst +++ b/docs/order_by_two.rst @@ -1,6 +1,7 @@ -어떻게 두 개의 필드를 정렬할까요? +여러 개의 필드를 기준으로 정렬하는 방법이 있나요? +=============================================================================== -쿼리셋의 :code:`order_by` 메서드는 하나 이상의 필드의 이름을 가질 수 있습니다. 즉, 두 개 이상의 필드를 기준으로 정렬할 수 있습니다. +쿼리셋의 :code:`order_by` 메서드에 여러 개의 정렬 기준 필드를 인자로 전달할 수 있습니다. 그러면 여러 개의 필드를 기준으로 정렬이 수행됩니다. .. code-block:: ipython From db6759941f5d3b657bc2c677ec6b5dbde5edf740 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 19:02:34 +0900 Subject: [PATCH 067/100] order_by_related_model --- docs/order_by_related_model.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/order_by_related_model.rst b/docs/order_by_related_model.rst index 95ac1fa..69d084e 100644 --- a/docs/order_by_related_model.rst +++ b/docs/order_by_related_model.rst @@ -1,7 +1,7 @@ 외래 키로 연결된 다른 표의 열을 기준으로 정렬할 수 있나요? ========================================================================== -:code:`Category` 모델과 :code:`Hero` 모델이 다음과 같이 외래 키로 연결되어 있습니다. +:code:`Category` 모델과 :code:`Hero` 모델이 다음과 같이 외래 키(ForeignKey)로 연결되어 있습니다. .. code-block:: python From c96fb006f0da88d0623864f2328d7d39966649d6 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 19:05:45 +0900 Subject: [PATCH 068/100] order_by_annotated_field --- docs/order_by_annotated_field.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/order_by_annotated_field.rst b/docs/order_by_annotated_field.rst index 286e0a5..9e8f6ed 100644 --- a/docs/order_by_annotated_field.rst +++ b/docs/order_by_annotated_field.rst @@ -1,6 +1,7 @@ -Annotate된 필드를 어떻게 정렬할 수 있을까요? +계산 필드를 기준으로 정렬할 수 있나요? +========================================================================== -:code:`Category` 와 :code:`Hero` 모델이 있습니다. +:code:`Category` 모델과 :code:`Hero` 모델이 있습니다. .. code-block:: python @@ -14,7 +15,7 @@ Annotate된 필드를 어떻게 정렬할 수 있을까요? category = models.ForeignKey(Category, on_delete=models.CASCADE) -:code:`Category` 안에 속한 :code:`Hero` 의 숫자에 따라 정렬하고 싶다면, 다음과 같이 할 수 있습니다. +:code:`Category` 항목들을 각 :code:`Category` 항목에 속한 :code:`Hero` 항목의 개수에 따라 정렬하고 싶다면, 다음과 같이 :code:`annotate` 메서드로 계산 필드를 준비하여 기준으로 삼을 수 있습니다. .. code-block:: python From 0fbc17d32758cb089f7e2da2b8b761d06a3efff9 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 19:23:10 +0900 Subject: [PATCH 069/100] one_to_one --- docs/one_to_one.rst | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/docs/one_to_one.rst b/docs/one_to_one.rst index 67fce36..1553b79 100644 --- a/docs/one_to_one.rst +++ b/docs/one_to_one.rst @@ -1,10 +1,9 @@ -일대일 관계는 어떻게 모델링하는가? -=============================================== +일대일 관계를 나타내는 방법은 무엇인가요? +=================================================== -| 관계 테이블의 한 레코드에 상응하는 단 하나의 레코드가 있을때 일대일 관계가 발생합니다. -| 여기 우리가 잘 알고 있는 예시가 있습니다. 각 개인은 단 하나의 생물학적 부모 즉, 어머니와 아버지를 가질 수 있습니다. -| -| 우리는 사용자 인증 모델을 가지고 있으므로, 아래에 설명한 대로 새로운 UserParent 모델을 추가할 것입니다. +일대일 관계란 두 표에서 각 항목이 서로 다른 표의 항목 단 하나와 연결되는 관계입니다. 우리가 쉽게 이해할 수 있는 예를 들자면, 우리들 각자는 생부와 생모를 각각 하나씩만 가질 수 있습니다. + +다음 예는 장고의 사용자 인증 모델에 :code:`UserParent` 모델을 일대일 관계로 연결해서 각 사용자마다 사용자의 부모를 기록할 수 있도록 합니다. .. code-block:: python @@ -30,9 +29,8 @@ >>> p2.user.last_name 'Upadhyay' -| on_delete 메서드는 Django에 삭제하려는 모델 인스턴스에 의존하는 모델 인스턴스를 어떻게 처리해야 할지 지시합니다. (예: ForeignKey 관계) -| on_delete=models.CASCADE는 계단식 삭제 즉, 종속모델까지 삭제하도록 Django에 지시합니다. +on_delete 메서드는 그 필드에 연결된 항목이 삭제될 때 그 항목을 가리키는 항목들을 어떻게 처리해야 할지 설정합니다. 예를 들어, :code:`on_delete=models.CASCADE`(하위 삭제)는 연결된 항목이 삭제될 때 해당 항목을 함께 삭제하도록 합니다. 따라서, 다음 코드를 실행하면 >>> u2.delete() -이것은 ``UserParent`` 의 관계 레코드까지 함께 삭제합니다. +:code:`User` 모델의 항목(u2) 뿐 아니라 :code:`UserParent`의 항목(p2)도 함께 삭제됩니다. From 9bffffc93e71f1c7ef92b0250e5d0e8cacbac328 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 19:32:51 +0900 Subject: [PATCH 070/100] one_to_one --- docs/one_to_one.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/one_to_one.rst b/docs/one_to_one.rst index 1553b79..cf15cf2 100644 --- a/docs/one_to_one.rst +++ b/docs/one_to_one.rst @@ -1,4 +1,4 @@ -일대일 관계를 나타내는 방법은 무엇인가요? +일대일 관계는 어떻게 나타내나요? =================================================== 일대일 관계란 두 표에서 각 항목이 서로 다른 표의 항목 단 하나와 연결되는 관계입니다. 우리가 쉽게 이해할 수 있는 예를 들자면, 우리들 각자는 생부와 생모를 각각 하나씩만 가질 수 있습니다. From 6b3492761dd3cf9aace1dbcdd8d498e20adde502 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 19:32:59 +0900 Subject: [PATCH 071/100] one_to_many --- docs/one_to_many.rst | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/docs/one_to_many.rst b/docs/one_to_many.rst index 7ded570..9635d73 100644 --- a/docs/one_to_many.rst +++ b/docs/one_to_many.rst @@ -1,10 +1,9 @@ -일대다 관계는 어떻게 모델링하는가? -=============================================== +일대다 관계는 어떻게 나타내나요? +=================================================== -| 관계형 데이터베이스에서는 한 테이블의 상위 레코드가 다른 테이블의 여러 하위 레코드를 참조할 수 있는 경우 일대다 관계가 발생합니다. -| 일대다 관계에서 상위 레코드가 하위 레코드를 필수적으로 가질 필요는 없습니다. 따라서 일대다 관계는 0개의 하위 레코드, 하나의 하위 레코드 또는 여러 개의 하위 레코드를 허용합니다. -| -| 일대다 관계를 정의하려면 ForeignKey를 사용하세요. +일대다 관계란 한 표의 상위 항목이 다른 표의 여러 하위 항목에서 참조되는 관계입니다. 일대다 관계에서 상위 항목이 반드시 하위 항목을 가진다는 보장은 없습니다. 상위 항목은 하위 항목을 0개, 1개, 여러 개 가질 수 있습니다. + +장고 모델에서 일대다 관계를 정의할 때는 :code:`ForeignKey` 필드를 사용합니다. .. code-block:: python @@ -31,10 +30,10 @@ >>> a1.reporter -객체를 저장하기 전에 객체를 할당하려고 하면 ValueError가 발생합니다. +상위 객체를 데이터베이스에 저장하지 않은 채로 하위 객체에 할당하려 하면 :code:`ValueError` 예외가 발생합니다. >>> u3 = User(username='someuser', first_name='Some', last_name='User', email='some@example.com') ->>> Article.objects.create(headline="This is a test", pub_date=date(2018, 3, 7), reporter=u1) +>>> Article.objects.create(headline="This is a test", pub_date=date(2018, 3, 7), reporter=u3) Traceback (most recent call last): ... ValueError: save() prohibited to prevent data loss due to unsaved related object 'reporter'. @@ -42,4 +41,4 @@ ValueError: save() prohibited to prevent data loss due to unsaved related object >>> Article.objects.filter(reporter=u1) , ]> -위의 쿼리셋은 u1의 여러 개의 ``Articles`` 를 보여줍니다. 따라서 일대다 관계임을 알 수 있습니다. +위 코드에서 구한 쿼리셋을 보면, u1 하나에 여러 개의 :code:`Article`이 연결되어 있음(일대다 관계)을 확인할 수 있습니다. From aa38e068e782e67707a9d05a265411225e773930 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 19:50:16 +0900 Subject: [PATCH 072/100] many_to_many --- docs/many_to_many.rst | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/docs/many_to_many.rst b/docs/many_to_many.rst index 3bbca11..2dfcfb0 100644 --- a/docs/many_to_many.rst +++ b/docs/many_to_many.rst @@ -1,15 +1,11 @@ -다대다 관계는 어떻게 모델링하는가? -=============================================== +다대다 관계는 어떻게 나타내나요? +=================================================== -| 다대다 관계는 하나의 레코드가 관계테이블의 여러 하위 레코드를 가질 수 있으며, 반대로도 가능합니다. -| -| 인터렉티브한 것을 만들기 위해서, 트위터 앱에 관해 이야기 하려고 합니다. -| 우리는 몇 개의 필드와 ManyToMany 필드를 이용하여 간단한 트위터 앱을 만들 수 있습니다. -| 트위터에는 트윗, 팔로워, 마음에 들어요/마음에 들어요 취소 와 같은 세 가지 기본적인 항목이 있습니다. -| -| 여기에 이 모든 것이 작동하는 두 개의 모델이 있습니다. 우리는 여기서 Django의 auth_user를 상속할 것입니다. +다대다 관계란 한 표의 항목이 다른 표의 항목 여러 개를 가리킬 수 있고, 반대로 다른 표의 항목이 그 표의 항목을 여러 개 가리킬 수도 있는 관계입니다. -.. code-block :: python +실제로 실행 가능한 예로, 트위터 앱을 다뤄 보겠습니다. 필드 몇 개와 :code:`ManyToMany` 필드만 있으면 간단한 트위터 앱을 만들 수 있습니다. + +트위터의 핵심 기능으로 '트윗', '팔로우', '마음에 들어요'가 있습니다. 아래의 두 모델로 그 핵심 기능을 모두 구현할 수 있습니다. :code:`User` 모델은 장고의 사용자 인증 모델을 확장하여 정의했습니다. :: class User(AbstractUser): tweet = models.ManyToManyField(Tweet, blank=True) @@ -23,15 +19,13 @@ def __unicode__(self): return self.tweet -위에 정의된 모델은 어떤 것이 가능할까요? - -:: +이 모델로 할 수 있는 일은 다음과 같습니다. :: - 1) 사용자는 다른 사용자를 팔로우/팔로우 취소를 할 수 있습니다. - 2) 사용자는 팔로잉하고 있는 사용자가 작성한 트윗을 볼 수 있습니다. - 3) 사용자는 트윗에 마음에 들어요/마음에 들어요 취소를 할 수 있습니다. + 1) 사용자가 다른 사용자를 '팔로우' 및 취소할 수 있습니다. + 2) 사용자가 팔로우하는 다른 사용자가 작성한 트윗을 볼 수 있습니다. + 3) 사용자가 트윗에 '마음에 들어요' 및 취소할 수 있습니다. -다대다 관계를 사용하여 수행할 수 있는 몇 가지 작업이 있습니다. +:code:`ManyToMany` 필드로 수행할 수 있는 연산을 몇 가지 살펴볼 텐데, 그 전에 항목을 몇 개 생성해 둡시다. >>> t1 = Tweet(tweet="I am happy today") >>> t1.save() @@ -44,23 +38,24 @@ >>> u3 = User(username='someuser', first_name='Some', last_name='User', email='some@example.com') >>> u3.save() -| 여기까지는 ManyToMany 필드의 어떤 용법도 사용하지 않은 채, 몇 개의 트윗과 사용자를 생성했습니다. -| 다음에는 이것들을 연결해봅시다. +생성한 항목들을 :code:`ManyToMany` 필드로 연결해 봅시다. :: >>> u2.tweet.add(t1) >>> u2.save() >>> u2.tweet.add(t2) >>> u2.save() ->>> # 사용자는 다른 사용자를 팔로우할 수 있습니다. +>>> # 사용자가 다른 사용자를 '팔로우' 할 수 있습니다. >>> u2.follow.add(u1) >>> u2.save() ->>> # 트윗은 사용자에게 연결되어 있습니다. 이제 사용자들이 트윗에 마음에 들어요/마음에 들어요 취소를 하게 할 수 있습니다. +>>> # 트윗이 사용자에 연결되어 있습니다. 사용자들이 트윗에 마음에 들어요 및 취소를 할 수 있습니다. >>> t1.favorite.add(u1) >>> t1.save() >>> t1.favorite.add(u3) >>> t1.save() ->>> # 사용자가 마음에 들어요 한 것을 취소하려면 +>>> # '마음에 들어요' 취소하기 >>> t1.favorite.remove(u1) >>> t1.save() -작동하는 예제는 여기에서 볼 수 있습니다. : https://github.com/yashrastogi16/simpletwitter +완전히 동작하는 예제는 다음 저장소에서 확인해 주세요. + +https://github.com/yashrastogi16/simpletwitter From 4920031948bae8a3fb238ae4e152f6c4265b5a01 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 19:54:01 +0900 Subject: [PATCH 073/100] self_fk --- docs/self_fk.rst | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/docs/self_fk.rst b/docs/self_fk.rst index b3173eb..e013387 100644 --- a/docs/self_fk.rst +++ b/docs/self_fk.rst @@ -1,18 +1,16 @@ -How to include a self-referencing ForeignKey in a model -모델에 자기 참조 외래키를 어떻게 포함하는가? +모델에 자기 참조 외래키를 정의할 수 있나요? ======================================================================== -| 자신을 참조하는 외래키는 중첩 또는 재귀 관계 모델에 사용합니다. -| 일대다 관계가 작동하는 것과 유사하지만 이름에서 알 수 있듯 모델은 자기 자신을 참조합니다. -| -| 자기 참조 외래키는 두 가지 방법으로 작성할 수 있습니다. +자기 참조 외래키(:code:`ForeignKey`)를 이용하여 중첩 관계·재귀 관계를 표현할 수 있습니다. 일대다 관계와 유사하지만, 이름에서 알 수 있듯이 모델이 자기 자신을 참조한다는 특징이 있습니다. + +자기 참조 외래키는 아래의 두 가지 방법으로 작성할 수 있습니다. .. code-block:: python class Employee(models.Model): manager = models.ForeignKey('self', on_delete=models.CASCADE) - # OR + # 또는 class Employee(models.Model): manager = models.ForeignKey("app.Employee", on_delete=models.CASCADE) From f38ac945b197ac08fa40ec876dbd78e1c3c722cc Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 20:02:15 +0900 Subject: [PATCH 074/100] existing_database --- docs/existing_database.rst | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/docs/existing_database.rst b/docs/existing_database.rst index 0f4b3ed..566d2b9 100644 --- a/docs/existing_database.rst +++ b/docs/existing_database.rst @@ -1,21 +1,12 @@ -이미 존재하는 데이터베이스를 어떻게 장고 모델로 변환하는가? -===================================================== +기존 데이터베이스를 장고 모델로 옮길 수 있나요? +================================================================================ -| Django 에는 존재하는 데이터베이스를 검토하여 모델로 생성할 수 있는 ``inspectdb`` 라는 기능이 있습니다. -| 다음과 같은 명령어로 결과를 확인할 수 있습니다. - - -:: +장고에는 기존 데이터베이스를 분석하여 그에 맞는 모델을 생성해주는 :code:`inspectdb` 명령이 있습니다. 셸에서 다음 명령을 실행하여 결과를 확인할 수 있습니다. :: $ python manage.py inspectdb -| 실행하기 전 반드시 ``settings.py`` 파일에 변환하려는 데이터베이스를 정의해야 합니다. -| 결과는 각 테이블의 모델을 담은 파일이 될 것입니다. - -다음과 같이 파일을 저장할 수 있습니다. - -:: +이 명령을 실행하려면 먼저 :code:`settings.py` 파일에 분석하려는 데이터베이스의 접속 정보를 설정해 두어야 합니다. 출력 결과는 생성된 모델의 파이썬 코드입니다. 코드를 파이썬 모듈 파일로 저장하려면 다음과 같이 셸의 스트림 리디렉션 기능을 이용합니다. :: $ python manage.py inspectdb > models.py -위의 명령으로 결과 파일이 현재 디렉토리에 저장될 것입니다. 해당 파일을 앱의 올바른 위치로 이동시키면 추가적인 커스텀을 시작할 수 있게 됩니다. +위 명령을 실행하면 분석된 모델이 파이썬 모듈 파일로 현재 디렉토리에 저장될 것입니다. 이 파일을 앱의 올바른 위치로 옮긴 뒤, 적절히 수정하여 사용하면 됩니다. From a8fc5337f7da3bf9156ef7fc2192b8cbc850a6ff Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 20:18:02 +0900 Subject: [PATCH 075/100] database_view --- docs/database_view.rst | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/docs/database_view.rst b/docs/database_view.rst index 49504d8..816b254 100644 --- a/docs/database_view.rst +++ b/docs/database_view.rst @@ -1,16 +1,13 @@ -어떻게 데이터베이스 뷰에 모델을 추가하는가? -=============================================== +데이터베이스 뷰에 대응하는 모델을 정의할 수 있나요? +========================================================================== -| 데이터베이스 뷰는 쿼리로 정의된 데이터베이스에서 검색 가능한 객체입니다. -| 비록 뷰가 데이터를 저장하지는 않지만, 어떤 것들은 "가상 테이블"이라 불리며 테이블처럼 쿼리를 할 수 있습니다. -| 뷰는 조인을 사용해 둘 혹은 그 이상의 테이블에서 데이터를 조합할 수 있으며, 정보의 하위 부분만 포함합니다. -| 이로 인해 복잡한 쿼리를 쉽게 추상화하거나 은닉할 수 있습니다. +데이터베이스 뷰는 데이터베이스 내에서 조회할 수 있도록 질의문으로 정의된 객체입니다. 뷰가 데이터를 물리적으로 저장하는 것은 아니지만, 실제 표와 같이 조회할 수 있기 때문에 '가상 표'라고 불리기도 합니다. 뷰는 여러 표를 결합(JOIN)한 정보를 보여줄 수도 있고, 한 표의 부분 집합만을 보여줄 수도 있습니다. 이를 활용하면 복잡한 질의문을 감추고 필요한 정보를 쉽게 조회하는 인터페이스를 만들 수 있습니다. -우리의 SqliteStuio에는 26개의 테이블을 볼 수 있고 뷰는 없습니다. +다음 스크린샷은 데이터베이스를 SQLiteStudio로 열어 본 모습입니다. 표가 26개 있고, 뷰는 없습니다. .. image:: before_view.png -간단한 뷰를 만들어봅시다. +SQL 질의문을 실행하여 간단한 뷰를 생성하겠습니다. .. code-block:: sql @@ -18,13 +15,11 @@ select id, first_name from auth_user; -뷰가 생성된 후, 우리는 26개의 테이블과 1개의 뷰를 확인할 수 있습니다. +뷰가 생성되어 표 26개와 뷰 1개가 있습니다. .. image:: after_view.png -앱에서 ``managed = False`` , ``db_table="temp_user"`` 로 관련 모델을 생성할 수 있습니다. - -.. code-block:: python +장고 앱에서는 모델을 정의할 때 메타(:code:`Meta`) 클래스에 :code:`managed = False`, :code:`db_table="temp_user"`와 같이 옵션을 설정하여 뷰를 가리키는 모델로 사용할 수 있습니다. :: class TempUser(models.Model): first_name = models.CharField(max_length=100) @@ -33,14 +28,16 @@ managed = False db_table = "temp_user" ->>> # 테이블에 수행하는 것과 유사하게 새로 생성된 뷰에 쿼리를 할 수 있습니다. ->>> TempUser.objects.all().values() - ->>> # 뷰에 새로운 레코드를 삽입할 수는 없습니다. ->>> TempUser.objects.create(first_name='Radhika', id=15) -Traceback (most recent call last): -... -django.db.utils.OperationalError: cannot modify temp_user because it is a view + >>> # 실제 표와 마찬가지로 뷰를 조회할 수 있습니다. + >>> TempUser.objects.all().values() + + >>> # 그러나 뷰에 기록은 하지 못합니다. + >>> TempUser.objects.create(first_name='Radhika', id=15) + Traceback (most recent call last): + ... + django.db.utils.OperationalError: cannot modify temp_user because it is a view + +union 연산이 있는 뷰는 아래 주소의 문서(Django Admin Cookbook)를 참고하세요. -union 연산이 있는 뷰는 다음을 참고하세요 : http://books.agiliq.com/projects/django-admin-cookbook/en/latest/database_view.html?highlight=view + From de1387b49f795995882dd75b0cea86ebb8292f27 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 20:42:13 +0900 Subject: [PATCH 076/100] generic_models --- docs/generic_models.rst | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/docs/generic_models.rst b/docs/generic_models.rst index 0feb227..03477a9 100644 --- a/docs/generic_models.rst +++ b/docs/generic_models.rst @@ -1,7 +1,7 @@ -어떤 종류의 객체와도 연관 지을 수 있는 Generic 모델을 만드는 방법은? (예: 카테고리 또는 코멘트) -============================================================================================================= +분류·댓글처럼 아무 모델에서나 참조할 수 있는 범용 모델을 정의할 수 있나요? +============================================================================================================ -다음과 같은 모델이 있습니다. +다음 모델을 봐 주세요. .. code-block:: python @@ -25,9 +25,7 @@ # ... -| ``Category`` 는 일반적인 모델입니다. 당신은 아마도 여러 모델 클래스 오브젝트에 카테고리를 적용하고 싶을 것입니다. -| 그렇다면 다음과 같이 할 수 있습니다. - +여기서 :code:`Category` 모델은 범용 모델로 고쳐 정의할 수 있습니다. 다른 모델에도 분류를 적용하고 싶을 테니까요. 다음과 같이 수정하면 됩니다. .. code-block:: python @@ -53,35 +51,34 @@ flex_category = GenericRelation(FlexCategory, related_query_name='flex_category') # ... -| ``FlexCategory`` 에 ``ForeignKey`` 와 ``PositiveIntegerField`` 를 사용하여 ``GenericForeignKey`` 필드를 적용했습니다. -| 그리고 카테고리를 적용하려는 모델에 ``GenericRelation`` 을 추가했습니다. -| -| 데이터베이스 레벨에서 보면 다음과 같습니다. +수정한 코드에서는 :code:`FlexCategory` 모델에 외래 키 필드(:code:`ForeignKey`) 하나와 양의 정수 필드(:code:`PositiveIntegerField`) 하나를 정의하여 범용 외래 키 필드(:code:`GenericForeignKey`)를 사용할 수 있도록 하였습니다. 그리고 분류를 이용할 모델에 범용 관계 필드(:code:`GenericRelation`)를 추가했습니다. + +:code:`FlexCategory` 모델의 데이터베이스 스키마는 다음과 같이 정의됩니다. + +.. code-block + Column | Type | Modifiers + -----------------+-----------------------+-------------------------------------------------------------------- + id | integer | not null default nextval('entities_flexcategory_id_seq'::regclass) + name | character varying(50) | not null + object_id | integer | not null + content_type_id | integer | not null -================== ======================= ==================================================================== - Column Type Modifiers -================== ======================= ==================================================================== - id integer not null default nextval('entities_flexcategory_id_seq'::regclass) - name character varying(50) not null - object_id integer not null - content_type_id integer not null -================== ======================= ==================================================================== -``Hero`` 는 다음과 같이 카테고리를 생성할 수 있습니다. +:code:`Hero` 모델의 항목을 분류할 때는 다음과 같이 합니다. .. code-block:: python hero = Hero.objects.create(name='Hades') FlexCategory.objects.create(content_object=hero, name="mythic") -'ghost'로 분류된 ``Hero`` 는 다음과 같이 얻을 수 있습니다. +'ghost'로 분류된 :code:`Hero`를 구하려면 다음과 같이 조회합니다. .. code-block:: python Hero.objects.filter(flex_category__name='ghost') -위의 쿼리는 다음과 같은 sql을 만듭니다. +위의 ORM 코드가 생성하는 SQL 질의문은 아래와 같습니다. .. code-block:: sql From 77bcc9fcc4b0b8893c9af847b592eef56e12e5f0 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 20:43:11 +0900 Subject: [PATCH 077/100] generic_models --- docs/generic_models.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/generic_models.rst b/docs/generic_models.rst index 03477a9..a1f03af 100644 --- a/docs/generic_models.rst +++ b/docs/generic_models.rst @@ -1,4 +1,4 @@ -분류·댓글처럼 아무 모델에서나 참조할 수 있는 범용 모델을 정의할 수 있나요? +분류·댓글처럼 아무 모델이나 가리킬 수 있는 범용 모델을 정의할 수 있나요? ============================================================================================================ 다음 모델을 봐 주세요. From c978b7e7cc10b8980d9c783e92dfd8f223ebaddd Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 20:49:20 +0900 Subject: [PATCH 078/100] table_names --- docs/table_name.rst | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/docs/table_name.rst b/docs/table_name.rst index 1c15699..0e6b3a7 100644 --- a/docs/table_name.rst +++ b/docs/table_name.rst @@ -1,16 +1,13 @@ -How to specify the table name for a model? -=============================================== +모델에 연결된 표의 이름을 지정할 수 있나요? +========================================================================= +여러분이 모델에 연결된 데이터베이스 표의 이름을 직접 지정하지 않으면 장고가 자동으로 표의 이름을 지어 줍니다. 자동으로 붙는 데이터베이스 표의 이름은 "앱의 레이블"(manage.py startapp 명령에서 지은 이름)과 모델 클래스의 이름을 밑줄 기호로 연결한 것이 됩니다. -To save you time, Django automatically derives the name of the database table from the name of your model class and the app that contains it. -A model’s database table name is constructed by joining the model’s “app label” – the name you used in manage.py startapp – to the model’s class name, -with an underscore between them. - -We have two apps in our demo application i.e., :code:`entities` and :code:`events` so all the models in them will have app names as the prefixes followed by `_` then the model name. +이 책의 예제에서는 :code:`entities` 앱과 :code:`events` 앱을 사용했으므로 모든 모델의 표 이름이 :code:`entities_` 또는 :code:`events_`로 시작합니다. .. image:: db_table.png -For renaming them we cab use :code:`db_table` parameter :: +이 이름을 직접 붙이시려면 모델의 :code:`Meta` 클래스에 :code:`db_table` 값을 설정하면 됩니다. :: class TempUser(models.Model): first_name = models.CharField(max_length=100) From c4563ad27fe1a154d5e594a40ff5ed4145e6cc7e Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 20:53:58 +0900 Subject: [PATCH 079/100] column_name --- docs/column_name.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/column_name.rst b/docs/column_name.rst index b2bf19c..602156c 100644 --- a/docs/column_name.rst +++ b/docs/column_name.rst @@ -1,7 +1,7 @@ -How to specify the column name for model field? -===================================================== +모델 필드의 데이터베이스 열 이름을 지정할 수 있나요? +============================================================================= -Naming of a column in the model can be achieved py passing a :code:`db_column` parameter with some name. If we don't pass this parameter django creates a column with the field name which we give. :: +모델 필드가 가리키는 데이터베이스의 열 이름을 지정하려면 필드 인스턴스의 초기화 매개변수 :code:`db_column`에 원하는 이름을 전달하면 됩니다. 이 매개변수에 인자를 전달하지 않으면 필드 이름과 동일한 이름이 사용됩니다. :: class ColumnName(models.Model): a = models.CharField(max_length=40,db_column='column1') @@ -12,4 +12,4 @@ Naming of a column in the model can be achieved py passing a :code:`db_column` p .. image:: db_column.png -Above we can :code:`db_column` has higher priority over :code:`field name`. First column is named as column1 but not as a. +위 예에서 보듯, :code:`db_column`으로 지정한 이름이 필드 이름보다 우선순위가 높습니다. 첫 번째 열의 이름이 a가 아니라 column1로 지어졌습니다. From aa233f195e67d91e835af4b3257109096838a252 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 20:55:19 +0900 Subject: [PATCH 080/100] index --- docs/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 6d32e97..333f652 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -57,7 +57,7 @@ datetime -질의 결과를 정렬하는 방법 +조회 결과를 정렬하는 방법 ================================================================ .. toctree:: @@ -71,7 +71,7 @@ order_by_annotated_field -데이터베이스 모델을 설계하는 방법 +모델을 정의하는 방법 =============================================================== .. toctree:: From 68eaccbd4059293c26b8b1175ab4ee644f3ffd1d Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 21:07:44 +0900 Subject: [PATCH 081/100] null_vs_blank --- docs/null_vs_blank.rst | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/null_vs_blank.rst b/docs/null_vs_blank.rst index 54bdac2..503ceae 100644 --- a/docs/null_vs_blank.rst +++ b/docs/null_vs_blank.rst @@ -1,19 +1,20 @@ -What is the difference between :code:`null=True` and :code:`blank=True`? -=============================================================================== +:code:`null=True`와 :code:`blank=True`의 차이가 무엇인가요? +==================================================================================================== -The default value of both :code:`null` and :code:`blank` is :code:`False`. Both of these values work at field level i.e., whether we want to keep a field null or blank. +:code:`null`와 :code:`blank`는 둘 다 기본값이 :code:`False`입니다. 이 두 설정은 모두 필드(열) 수준에서 동작합니다. 즉, 필드(열)를 비워두는 것을 허용할 것인지를 설정합니다. -:code:`null=True` will set the field's value to NULL i.e., no data. It is basically for the databases column value. :: +:code:`null=True`는 필드의 값이 NULL(정보 없음)로 저장되는 것을 허용합니다. 결국 데이터베이스 열에 관한 설정입니다. :: date = models.DateTimeField(null=True) -:code:`blank=True` determines whether the field will be required in forms. This includes the admin and your own custom forms. :: +:code:`blank=True`는 필드가 폼(입력 양식)에서 빈 채로 저장되는 것을 허용합니다. 장고 관리자(admin) 및 직접 정의한 폼에도 반영됩니다. :: - title = models.CharField(blank=True) // title can be kept blank. In the database ("") will be stored. + title = models.CharField(blank=True) # 폼에서 비워둘 수 있음. 데이터베이스에는 ''이 저장됨. -:code:`null=True` :code:`blank=True` This means that the field is optional in all circumstances. :: +:code:`null=True`와 :code:`blank=True`를 모두 지정하면 어떤 경우로든 비워둘 수 있음을 의미합니다. :: epic = models.ForeignKey(null=True, blank=True) - // The exception is CharFields() and TextFields(), which in Django are never saved as NULL. Blank values are stored in the DB as an empty string (''). + # 단, CharFields()와 TextFields()에서는 예외입니다. + # 장고는 이 경우 NULL을 저장하지 않으며, 빈 값을 빈 문자열('')로 저장합니다. -Also there is a special case, when you need to accept NULL values for a :code:`BooleanField`, use :code:`NullBooleanField`. \ No newline at end of file +또 하나 예외적인 경우가 있습니다. 불리언 필드(:code:`BooleanField`)에 NULL을 입력할 수 있도록 하려면 :code:`null=True`를 설정하는 것이 아니라, 널 불리언 필드(:code:`NullBooleanField`)를 사용해야 합니다. \ No newline at end of file From cc1ac24f540fff6a66ad1e83bcf17da3de9da0b8 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 21:18:09 +0900 Subject: [PATCH 082/100] uuid --- docs/uuid.rst | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/docs/uuid.rst b/docs/uuid.rst index 9c9fa4b..91eb5d4 100644 --- a/docs/uuid.rst +++ b/docs/uuid.rst @@ -1,11 +1,9 @@ -How to use a UUID instead of ID as prmary key? -++++++++++++++++++++++++++++++++++++++++++++++++++ +기본 키(PK)로 ID 대신 UUID를 사용할 수 있나요? +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -Whenever we create any new model, there is an ID field attached to it. The ID field's data type will be Integer by default. +장고에서 모델을 생성하면 ID 필드가 기본 키로 생성됩니다. ID 필드의 기본 데이터 유형은 양의 정수입니다. -To make id field as UUID, there is a new field type UUIDField which was added in django version 1.8+. - -Example :: +양의 정수가 아니라 UUID를 기본 키로 사용하고 싶다면 장고 1.8 버전에서 추가된 :code:`UUIDField`를 사용하면 됩니다. :: import uuid from django.db import models From 0ebbf2b8db2acf44645f55acfcd4a26f7c01ff78 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 21:18:14 +0900 Subject: [PATCH 083/100] slugfield --- docs/slugfield.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/slugfield.rst b/docs/slugfield.rst index df4ae68..2419807 100644 --- a/docs/slugfield.rst +++ b/docs/slugfield.rst @@ -1,8 +1,8 @@ -How to use slug field with django for more readability? -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +슬러그 필드를 사용할 수 있나요? +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +슬러그(`slug`)는 URL의 구성요소로 웹사이트의 특정 페이지를 가리키는 사람이 읽기 쉬운 형식의 식별자입니다. 장고에서는 :code:`SlugField`로 슬러그를 지원합니다. 다음 예에서 사용법을 확인하실 수 있습니다. 앞서 살펴보았던 :code:`Article` 모델에 슬러그 필드를 추가해 가독성을 높여 보았습니다. :: -Slug is a part of a URL which identifies a particular page on a website in a form readable by users. For making it work django offers us a slugfield. It can be implimented as under. -We already had a model :code:`Article` we will be adding slugfield to it to make it user readable. :: from django.utils.text import slugify class Article(models.Model): @@ -19,10 +19,10 @@ We already had a model :code:`Article` we will be adding slugfield to it to make >>> from datetime import date >>> a1 = Article.objects.create(headline="todays market report", pub_date=date(2018, 3, 6), reporter=u1) >>> a1.save() - // slug here is auto-generated, we haven't created it in the above create method. + # 슬러그는 자동으로 생성됩니다. create 메서드를 따로 정의한 게 아닙니다. >>> a1.slug 'todays-market-report' -Slug is useful because: - | it's human friendly (eg. /blog/ instead of /1/). - | it's good SEO to create consistency in title, heading and URL. +슬러그의 장점: + | 사람이 이해하기 좋다. (:code:`/1/` 보다 :code:`/blog/` 가 좋다) + | 제목과 URL을 동일하게 맞춰 검색엔진 최적화(SEO)에 도움이 된다. From 418388f19edb0f84804025a00f5dc46216470f1c Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 21:32:01 +0900 Subject: [PATCH 084/100] multiple_databases --- docs/multiple_databases.rst | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/docs/multiple_databases.rst b/docs/multiple_databases.rst index 2f8b046..0e13c9b 100644 --- a/docs/multiple_databases.rst +++ b/docs/multiple_databases.rst @@ -1,7 +1,7 @@ -How to add multiple databases to the django application ? -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +장고 프로젝트 하나에서 여러 개의 데이터베이스를 사용할 수 있나요? +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -The configuration of database related stuff is mostly done in :code:`settings.py` file. So to add multiple database to our django project we need add them in :code:`DATABASES` dictionary. :: +데이터베이스의 접속에 관련된 설정은 대부분 :code:`settings.py` 파일에서 이루어집니다. 장고 프로젝트에 여러 개의 데이터베이스를 추가하려면 해당 파일의 :code:`DATABASES` 사전에 등록하면 됩니다. :: DATABASE_ROUTERS = ['path.to.DemoRouter'] DATABASE_APPS_MAPPING = {'user_data': 'users_db', @@ -26,16 +26,15 @@ The configuration of database related stuff is mostly done in :code:`settings.py } } -With multiple databases it will be good to talk about :code:`Database Router`. The default routing scheme ensures that if a database isn’t specified, all queries fall back to the default database. :code:`Database Router` defaults to :code:`[]`. :: +여러 개의 데이터베이스를 함께 사용하려면 데이터베이스 중계기(database router)에 대해 알아야 합니다. 장고의 기본 중계 설정은 데이터베이스를 특정하지 않은 경우 기본 데이터베이스(default database)로 중계하는 것입니다. :code:`DATABASE_ROUTERS` 설정의 기본값은 :code:`[]` 입니다. 중계기는 다음과 같이 정의할 수 있습니다. :: class DemoRouter: """ - A router to control all database operations on models in the - user application. + user_data 앱의 모델에서 수행되는 모든 데이터베이스 연산을 제어하는 중계기 """ def db_for_read(self, model, **hints): """ - Attempts to read user models go to users_db. + user_data 앱의 모델을 조회하는 경우 users_db로 중계한다. """ if model._meta.app_label == 'user_data': return 'users_db' @@ -43,7 +42,7 @@ With multiple databases it will be good to talk about :code:`Database Router`. T def db_for_write(self, model, **hints): """ - Attempts to write user models go to users_db. + user_data 앱의 모델을 기록하는 경우 users_db로 중계한다. """ if model._meta.app_label == 'user_data': return 'users_db' @@ -51,7 +50,7 @@ With multiple databases it will be good to talk about :code:`Database Router`. T def allow_relation(self, obj1, obj2, **hints): """ - Allow relations if a model in the user app is involved. + user_data 앱의 모델과 관련된 관계 접근을 허용한다. """ if obj1._meta.app_label == 'user_data' or \ obj2._meta.app_label == 'user_data': @@ -60,15 +59,14 @@ With multiple databases it will be good to talk about :code:`Database Router`. T def allow_migrate(self, db, app_label, model_name=None, **hints): """ - Make sure the auth app only appears in the 'users_db' - database. + user_data 앱의 모델에 대응하는 표가 users_db 데이터베이스에만 생성되도록 한다. """ if app_label == 'user_data': return db == 'users_db' return None -Respective models would be modified as :: +위와 같은 중계기가 설정되었을 때, 서로 다른 데이터베이스를 사용하는 모델은 다음과 같이 정의할 수 있습니다. :: class User(models.Model): username = models.Charfield(ax_length=100) @@ -82,6 +80,6 @@ Respective models would be modified as :: class Meta: app_label = 'customer_data' -Few helpful commands while working with multiple databases. :: +여러 개의 데이터베이스를 관리할 때 사용하는 마이그레이션 명령입니다. :: $ ./manage.py migrate --database=users_db From 75f5652cd8e9e6c1240c2da414dfed7fc20356ea Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 21:35:26 +0900 Subject: [PATCH 085/100] numqueries --- docs/numqueries.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/numqueries.rst b/docs/numqueries.rst index 9915367..d229276 100644 --- a/docs/numqueries.rst +++ b/docs/numqueries.rst @@ -1,14 +1,14 @@ -함수가 고정된 개수의 쿼리를 실행하는지 확인하는 방법은? -======================================================================== +질의 횟수가 고정된 횟수만큼만 일어나는지 확인할 수 있을까요? +======================================================================================= -테스트에서 ``assertNumQueries()`` 메서드를 사용하면 쿼리의 개수를 확인할 수 있습니다. +장고 단위 테스트 클래스의 `assertNumQueries()` 메서드를 사용하여 데이터베이스에 발생하는 질의 횟수를 검증할 수 있습니다. .. code-block:: python def test_number_of_queries(self): User.objects.create(username='testuser1', first_name='Test', last_name='user1') - # 위의 ORM은 하나의 쿼리를 실행할 것입니다. + # 위 ORM 명령으로 질의 횟수가 1 번 일어나야 한다. self.assertNumQueries(1) User.objects.filter(username='testuser').update(username='test1user') - # 쿼리가 하나 더 추가되었습니다. + # 질의 횟수가 한 번 증가해야 한다. self.assertNumQueries(2) From 343a026a52d11a4ef3466dcbea252f559d1e2dc1 Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 21:39:26 +0900 Subject: [PATCH 086/100] keepdb --- docs/keepdb.rst | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/docs/keepdb.rst b/docs/keepdb.rst index f174405..8bc300f 100644 --- a/docs/keepdb.rst +++ b/docs/keepdb.rst @@ -1,12 +1,11 @@ -테스트 실행을 할 때, 데이터베이스 재사용으로 테스트 속도를 높이는 방법은? -================================================================ - -| ``python manage.py test`` 명령을 실행할 때 마다 새로운 데이터베이스가 생성됩니다. 마이그레이션이 많지 않다면 이것은 그다지 문제가 되지 않습니다. -| 하지만 마이그레이션이 많은 경우, 테스트를 실행할 때 데이터베이스 재생성에 많은 시간을 소요하게 됩니다. 이런 상황을 피하기 위해서 이전에 생성된 데이터베이스를 사용할 수 있습니다. -| -| 테스트 명령에 ``--keepdb`` 플래그를 추가하면 데이터베이스가 삭제되는 것을 막고 테스트 실행 간 데이터베이스를 유지할 수 있습니다. -| 데이터베이스가 존재하지 않으면, 우선 데이터베이스를 생성합니다. 마지막 테스트 실행 이후 마이그레이션이 추가되면, 최신 상태를 유지하기 위해 이를 적용합니다. -| +데이터베이스를 재사용하여 테스트 실행 속도를 높일 수 있나요? +============================================================================================ + +:code:`python manage.py test` 명령을 실행할 때마다 데이터베이스가 새로 생성됩니다. 이것은 마이그레이션이 많지 않을 때는 문제가 되지 않습니다. 하지만 마이그레이션이 많아질 수록 테스트 실행시 데이터베이스 재생성에 많은 시간을 소요하게 됩니다. 이런 상황을 피하기 위해 이전에 생성된 데이터베이스를 재사용할 수 있습니다. + +테스트 명령에 :code:`--keepdb` 플래그를 추가하여 데이터베이스가 삭제되는 것을 방지하고 테스트 실행 간 데이터베이스를 유지할 수 있습니다. +데이터베이스가 존재하지 않으면 데이터베이스를 새로 생성합니다. 마지막 테스트 실행 이후 마이그레이션이 추가되었으면 최신 상태를 유지하기 위해 마이그레이션을 수행합니다. + .. code-block:: bash $ python manage.py test --keepdb From 8931c9893e91cda11047ffa0c928626e8ea05a2b Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 21:43:49 +0900 Subject: [PATCH 087/100] refresh_from_db --- docs/refresh_from_db.rst | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/docs/refresh_from_db.rst b/docs/refresh_from_db.rst index 944d502..7bc39b9 100644 --- a/docs/refresh_from_db.rst +++ b/docs/refresh_from_db.rst @@ -1,17 +1,14 @@ -데이터베이스에서 모델 객체를 다시 로드하는 방법은? +모델 객체를 데이터베이스에서 다시 읽어들일 수 있나요? ======================================================================== -| ``refresh_from_db()`` 메서드를 사용하여 데이터베이스에서 모델을 다시 로드할 수 있습니다. -| 이것은 테스트에서 유용할 것입니다. 예를 들면, -| -.. code-block:: python +``refresh_from_db()`` 메서드를 사용하여 데이터베이스에서 모델을 다시 읽어들일 수 있습니다. 값을 갱신하는 테스트를 작성할 때 유용한 기능입니다. 다음 예를 살펴보세요. :: - class TestORM(TestCase): - def test_update_result(self): - userobject = User.objects.create(username='testuser', first_name='Test', last_name='user') - User.objects.filter(username='testuser').update(username='test1user') - # 여기에서 userobject의 이름은 여전히 'testuser'이지만, - # 데이터베이스에서는 'test1user'로 업데이트 되어있습니다. - # 속성이 업데이트 된 객체는 데이터베이스에서 다시 로드해야합니다. - userobject.refresh_from_db() - self.assertEqual(userobject.username, 'test1user') + class TestORM(TestCase): + def test_update_result(self): + userobject = User.objects.create(username='testuser', first_name='Test', last_name='user') + User.objects.filter(username='testuser').update(username='test1user') + # 이 때, userobject 인스턴스의 username은 'testuser' 입니다. + # 그러나 데이터베이스에서는 'test1user'로 수정되었습니다. + # 모델 인스턴스의 속성이 데이터베이스와 맞지 않으므로 다시 읽어들입니다. + userobject.refresh_from_db() + self.assertEqual(userobject.username, 'test1user') From b0250601d71c5443862bb0613d5c634864a2957e Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Sun, 30 Sep 2018 22:02:37 +0900 Subject: [PATCH 088/100] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 5c066a9..bdcfd5b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ ### 장고 ORM 요리책 +(렌더링 된 문서: https://django-orm-cookbook-ko.readthedocs.io/en/latest/) + 장고 ORM 요리책은 장고를 이용한 다양한 레시피(조리법)를 담은 책입니다. `장고 ORM/쿼리셋으로 ~을 하려면 어떻게 하나요?` 하는 50여 개의 질문과 답을 담고 있습니다. From a9b86ae99577688afa2bcd41400113bb67ec9b7b Mon Sep 17 00:00:00 2001 From: hshwang-jdlab <35677719+hshwang-jdlab@users.noreply.github.com> Date: Sun, 30 Sep 2018 23:33:45 +0900 Subject: [PATCH 089/100] Update query.rst --- docs/query.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/query.rst b/docs/query.rst index b512df5..e3d4488 100644 --- a/docs/query.rst +++ b/docs/query.rst @@ -1,9 +1,9 @@ 장고 ORM이 실행하는 실제 SQL 질의문을 확인할 수 있나요? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -장고 ORM이 실행하는 질의문 또는 우리가 작성한 코드에 대응하는 SQL 질의문이 무엇인지 확인하고 싶을 때가 있습니다. SQL 질의문을 구하고 싶은 :code:`queryset.query`의 :code:`str`을 확인하면 됩니다. 간단하죠? +장고 ORM이 실행하는 질의문 또는 우리가 작성한 코드에 대응하는 SQL 질의문이 무엇인지 확인하고 싶을 때가 있습니다. SQL 질의문을 구하고 싶은 :code:`queryset.query` 의 :code:`str` 을 확인하면 됩니다. 간단하죠? -:code:`Event`라는 모델이 있을 때, 이 모델의 모든 행을 데이터베이스에서 읽어오려면 :code:`Event.objects.all()`과 같은 코드를 작성하면 됩니다. 이렇게 구한 쿼리셋의 :code:`str(queryset.query)`를 확인하여 SQL 질의문을 살펴봅시다. +:code:`Event` 라는 모델이 있을 때, 이 모델의 모든 행을 데이터베이스에서 읽어오려면 :code:`Event.objects.all()` 과 같은 코드를 작성하면 됩니다. 이렇게 구한 쿼리셋의 :code:`str(queryset.query)` 를 확인하여 SQL 질의문을 살펴봅시다. .. code-block:: python From a842e1f9e3c43d778796a37d5501b370ee8fb83a Mon Sep 17 00:00:00 2001 From: Bak Yeon O Date: Mon, 1 Oct 2018 01:00:11 +0900 Subject: [PATCH 090/100] =?UTF-8?q?=EC=A1=B0=ED=8C=90=20=EC=98=A4=EB=A5=98?= =?UTF-8?q?=20=EC=88=98=EC=A0=95=20=EB=B0=8F=202=EC=B0=A8=20=ED=87=B4?= =?UTF-8?q?=EA=B3=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/aggregation.rst | 4 ++-- docs/and_query.rst | 4 +--- docs/case_insensitive.rst | 4 ++-- docs/column_name.rst | 4 ++-- docs/copy.rst | 2 +- docs/database_view.rst | 4 ++-- docs/datetime.rst | 1 + docs/distinct.rst | 2 +- docs/duplicate.rst | 4 ++-- docs/f_query.rst | 13 ++++++------- docs/filefield.rst | 2 +- docs/func_expressions.rst | 8 ++++---- docs/generic_models.rst | 2 +- docs/multiple_databases.rst | 6 +++--- docs/multiple_objects.rst | 2 +- docs/notequal_query.rst | 2 +- docs/null_vs_blank.rst | 12 ++++++------ docs/numqueries.rst | 2 +- docs/one_to_many.rst | 2 +- docs/one_to_one.rst | 3 +-- docs/or_query.rst | 2 +- docs/order_by_related_model.rst | 2 +- docs/random.rst | 8 ++++---- docs/second_largest.rst | 2 +- docs/select_some_fields.rst | 12 +++++------- docs/self_fk.rst | 6 +++--- docs/signals.rst | 4 ++-- docs/singleton.rst | 2 +- docs/slugfield.rst | 2 +- docs/subquery.rst | 6 +++--- docs/table_name.rst | 4 ++-- docs/truncate.rst | 4 ++-- docs/union.rst | 6 +++--- docs/update_denormalized_fields.rst | 6 +++--- docs/uuid.rst | 2 +- 35 files changed, 73 insertions(+), 78 deletions(-) diff --git a/docs/aggregation.rst b/docs/aggregation.rst index 5586d62..fbe3f07 100644 --- a/docs/aggregation.rst +++ b/docs/aggregation.rst @@ -1,5 +1,5 @@ -항목들을 집계하는 방법은 무엇인가요? -=========================================== +기록된 항목의 집계를 구할 수 있나요? +================================================================== 장고 ORM을 이용해 항목을 생성·조회·갱신·삭제할 수 있지만, 때로는 항목들의 집계값을 구하고 싶을 때가 있습니다. 장고 ORM에는 SQL의 일반적인 집계 기능을 수행하는 :code:`Max`, :code:`Min`, :code:`Avg`, :code:`Sum` 등의 함수가 있습니다. 다음은 이 집계 함수를 이용하는 예입니다. :: diff --git a/docs/and_query.rst b/docs/and_query.rst index 925567c..63ccdf4 100644 --- a/docs/and_query.rst +++ b/docs/and_query.rst @@ -3,7 +3,7 @@ AND 연산으로 여러 조건을 모두 만족하는 항목을 구하려면 어 .. image:: usertable.png -장고의 사용자 계정 관리 앱인 :code:`django.contrib.auth`를 사용하면 데이터베이스에 :code:`auth_user`이라는 표가 생성됩니다. 이 표에는 :code:`username`, :code:`first_name`, :code:`last_name` 등의 열이 있습니다. +장고의 사용자 계정 관리 앱인 :code:`django.contrib.auth` 를 사용하면 데이터베이스에 :code:`auth_user` 라는 표가 생성됩니다. 이 표에는 :code:`username`, :code:`first_name`, :code:`last_name` 등의 열이 있습니다. :code:`AND` 연산으로 여러 조건을 모두 만족하는 행을 구해야 하는 경우가 많습니다. 이름이 'R'로 시작하고 성이 'D'로 시작하는 모든 사용자를 구한다고 해 봅시다. @@ -19,8 +19,6 @@ AND 연산으로 여러 조건을 모두 만족하는 항목을 구하려면 어 위 조건의 SQL 질의문은 다음과 같이 생성됩니다. :: -.. code-block:: sql - SELECT username, first_name, last_name, email FROM auth_user WHERE first_name LIKE 'R%' AND last_name LIKE 'D%'; .. image:: sqluser_result2.png diff --git a/docs/case_insensitive.rst b/docs/case_insensitive.rst index 3a13a8e..ee1b0b0 100644 --- a/docs/case_insensitive.rst +++ b/docs/case_insensitive.rst @@ -10,7 +10,7 @@ >>> User.objects.all().order_by('username').values_list('username', flat=True) -텍스트 필드에서 대문자·소문자를 구별하지 않고 정렬하려면 다음과 같이 :code:`Lower`를 사용하면 됩니다. +텍스트 필드에서 대문자·소문자를 구별하지 않고 정렬하려면 다음과 같이 :code:`Lower` 를 사용하면 됩니다. .. code-block:: ipython @@ -18,7 +18,7 @@ >>> User.objects.all().order_by(Lower('username')).values_list('username', flat=True) -:code:`annotate` 메서드로 :code:`Lower`를 적용한 열을 준비하고, 그 열을 기준으로 정렬하는 방법도 가능합니다. +:code:`annotate` 메서드로 :code:`Lower` 를 적용한 열을 준비하고, 그 열을 기준으로 정렬하는 방법도 가능합니다. .. code-block:: python diff --git a/docs/column_name.rst b/docs/column_name.rst index 602156c..d267cc7 100644 --- a/docs/column_name.rst +++ b/docs/column_name.rst @@ -1,7 +1,7 @@ 모델 필드의 데이터베이스 열 이름을 지정할 수 있나요? ============================================================================= -모델 필드가 가리키는 데이터베이스의 열 이름을 지정하려면 필드 인스턴스의 초기화 매개변수 :code:`db_column`에 원하는 이름을 전달하면 됩니다. 이 매개변수에 인자를 전달하지 않으면 필드 이름과 동일한 이름이 사용됩니다. :: +모델 필드가 가리키는 데이터베이스의 열 이름을 지정하려면 필드 인스턴스의 초기화 매개변수 :code:`db_column` 에 원하는 이름을 전달하면 됩니다. 이 매개변수에 인자를 전달하지 않으면 필드 이름과 동일한 이름이 사용됩니다. :: class ColumnName(models.Model): a = models.CharField(max_length=40,db_column='column1') @@ -12,4 +12,4 @@ .. image:: db_column.png -위 예에서 보듯, :code:`db_column`으로 지정한 이름이 필드 이름보다 우선순위가 높습니다. 첫 번째 열의 이름이 a가 아니라 column1로 지어졌습니다. +위 예에서 보듯, :code:`db_column` 으로 지정한 이름이 필드 이름보다 우선순위가 높습니다. 첫 번째 열의 이름이 a가 아니라 column1로 지어졌습니다. diff --git a/docs/copy.rst b/docs/copy.rst index f484d14..a3bbfbf 100644 --- a/docs/copy.rst +++ b/docs/copy.rst @@ -3,7 +3,7 @@ 장고 ORM에는 모델 인스턴스를 복사하는 내장 메서드가 없습니다. 하지만 모든 필드의 값을 복사하여 새 인스턴스를 만들고 새로 저장하는 것은 어렵지 않습니다. -모델 인스턴스를 저장할 때, :code:`pk` 필드 값이 :code:`None`으로 지정되어 있으면 데이터베이스에 새 행으로 저장됩니다. :code:`pk` 열 외의 모든 필드 값은 그대로 복제됩니다. +모델 인스턴스를 저장할 때, :code:`pk` 필드 값이 :code:`None` 으로 지정되어 있으면 데이터베이스에 새 행으로 저장됩니다. :code:`pk` 외의 모든 필드 값은 그대로 복제됩니다. .. code-block:: ipython diff --git a/docs/database_view.rst b/docs/database_view.rst index 816b254..a62977d 100644 --- a/docs/database_view.rst +++ b/docs/database_view.rst @@ -3,7 +3,7 @@ 데이터베이스 뷰는 데이터베이스 내에서 조회할 수 있도록 질의문으로 정의된 객체입니다. 뷰가 데이터를 물리적으로 저장하는 것은 아니지만, 실제 표와 같이 조회할 수 있기 때문에 '가상 표'라고 불리기도 합니다. 뷰는 여러 표를 결합(JOIN)한 정보를 보여줄 수도 있고, 한 표의 부분 집합만을 보여줄 수도 있습니다. 이를 활용하면 복잡한 질의문을 감추고 필요한 정보를 쉽게 조회하는 인터페이스를 만들 수 있습니다. -다음 스크린샷은 데이터베이스를 SQLiteStudio로 열어 본 모습입니다. 표가 26개 있고, 뷰는 없습니다. +다음 스크린샷은 데이터베이스를 SQLiteStudio라는 프로그램으로 열어 본 모습입니다. 표가 26개 있고, 뷰는 없습니다. .. image:: before_view.png @@ -19,7 +19,7 @@ SQL 질의문을 실행하여 간단한 뷰를 생성하겠습니다. .. image:: after_view.png -장고 앱에서는 모델을 정의할 때 메타(:code:`Meta`) 클래스에 :code:`managed = False`, :code:`db_table="temp_user"`와 같이 옵션을 설정하여 뷰를 가리키는 모델로 사용할 수 있습니다. :: +장고 앱에서는 모델을 정의할 때 메타(:code:`Meta`) 클래스에 :code:`managed = False`, :code:`db_table="temp_user"` 와 같이 옵션을 설정하여 뷰를 가리키는 모델로 사용할 수 있습니다. :: class TempUser(models.Model): first_name = models.CharField(max_length=100) diff --git a/docs/datetime.rst b/docs/datetime.rst index 3475e4c..7ed8d9b 100644 --- a/docs/datetime.rst +++ b/docs/datetime.rst @@ -2,6 +2,7 @@ ============================================================================================= 장고에서 시간을 나타내는 텍스트를 다른 양식의 텍스트로 변환하여 데이터베이스에 저장하는 방법은 여러 가지가 있습니다. 몇 가지만 소개하겠습니다. + "2018-03-11"이라는 시간 텍스트가 있는데, 이 양식으로는 데이터베이스에 저장할 수 없다고 가정합시다. 아래와 같이 장고의 dateparser 모듈이나 파이썬 표준 라이브러리를 이용하여 날짜 양식을 변환할 수 있습니다. :: >>> user = User.objects.get(id=1) diff --git a/docs/distinct.rst b/docs/distinct.rst index aee1148..8a73f93 100644 --- a/docs/distinct.rst +++ b/docs/distinct.rst @@ -14,5 +14,5 @@ ).filter(name_count=1) records = User.objects.filter(first_name__in=[item['first_name'] for item in distinct]) -한편, :code:`User.objects.distinct("first_name").all()`와 같은 코드는 고유한 :code:`first_name`을 가진 사용자별로 첫번째 사용자를 구하는 코드입니다. 위 코드와는 실행 결과가 다릅니다. +한편, :code:`User.objects.distinct("first_name").all()` 와 같은 코드는 고유한 :code:`first_name` 을 가진 사용자별로 첫번째 사용자를 구하는 코드입니다. 위 코드와는 실행 결과가 다릅니다. diff --git a/docs/duplicate.rst b/docs/duplicate.rst index 9204b98..5cc3f61 100644 --- a/docs/duplicate.rst +++ b/docs/duplicate.rst @@ -1,9 +1,9 @@ 특정 열의 값이 동일한 항목은 어떻게 찾나요? -============================================== +========================================================== .. image:: usertable2.png -:code:`first_name`이 서로 동일한 사용자들을 구한다고 합시다. 특정 열에서 중복된 값을 찾을 때는 아래와 같이 :code:`Count`를 구한 뒤 중복 수를 기준으로 골라내면 됩니다. +:code:`first_name` 이 서로 동일한 사용자들을 구한다고 합시다. 특정 열에서 중복된 값을 찾을 때는 아래와 같이 :code:`Count` 를 구한 뒤 중복 수를 기준으로 골라내면 됩니다. .. code-block:: python diff --git a/docs/f_query.rst b/docs/f_query.rst index 445afc7..fa8057d 100644 --- a/docs/f_query.rst +++ b/docs/f_query.rst @@ -1,13 +1,12 @@ -열의 값을 서로 비교하여 항목을 선택할 수 있나요? +필드의 값을 서로 비교하여 항목을 선택할 수 있나요? ============================================================================== -장고 ORM에서 특정한 값을 기준으로 행을 선택하는 것은 간단합니다. 예를 들어, 이름(:code:`first_name`)이 :code:`'R'`로 시작하는 :code:`User` 모델의 행을 구하려면 -:code:`User.objects.filter(first_name__startswith='R')`와 같이 코드를 작성하면 됩니다. +장고 ORM에서 필드를 고정 값과 비교하여 항목을 선택하는 것은 간단합니다. 예를 들어, 이름(:code:`first_name`) 이 :code:`'R'` 로 시작하는 :code:`User` 모델의 행을 구하려면 +:code:`User.objects.filter(first_name__startswith='R')` 와 같이 코드를 작성하면 됩니다. -그런데 이름(:code:`first_name`)을 성(:code:`last_name`)과 비교하여 선택하려면 어떻게 해야 할까요? 이럴 때 :code:`F` 객체를 사용합니다. - -실습을 위해 User 행을 몇 개 생성합시다. +그런데 필드와 필드를 서로 비교할 수도 있을까요? 예를 들어, 이름(:code:`first_name`) 을 성(:code:`last_name`) 과 비교하여 선택하는 것이죠. 이럴 때 :code:`F` 객체를 사용합니다. +실습을 위해 :code:`User` 모델의 항목을 몇 개 생성합시다. .. code-block:: ipython @@ -25,7 +24,7 @@ In [29]: User.objects.filter(last_name=F("first_name")) Out[29]: ]> -:code:`F` 객체는 annotate 메서드로 계산해 둔 필드를 가리킬 때도 사용할 수 있습니다. 예를 들어, 이름의 첫 글자와 성의 첫 글자가 동일한 사용자를 구하고 싶다면 :code:`Substr("first_name", 1, 1)`를 사용할 수 있습니다. +:code:`F` 객체는 annotate 메서드로 계산해 둔 필드를 가리킬 때도 사용할 수 있습니다. 예를 들어, 이름의 첫 글자와 성의 첫 글자가 동일한 사용자를 구하고 싶다면 :code:`Substr("first_name", 1, 1)` 를 사용할 수 있습니다. .. code-block:: ipython diff --git a/docs/filefield.rst b/docs/filefield.rst index 41f0d07..3e4ad65 100644 --- a/docs/filefield.rst +++ b/docs/filefield.rst @@ -1,7 +1,7 @@ FileField에 파일이 들어있지 않은 행은 어떻게 구할 수 있나요? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -장고의 :code:`FileField`와 :code:`ImageField`는 파일과 이미지 파일의 경로를 저장합니다. 이것은 응용 수준에서의 구별이고, 데이터베이스 수준에서는 모두 :code:`CharField`와 동일한 방식으로 저장됩니다. 파일이 없는 행을 구하려면 다음 코드를 실행하면 됩니다. +장고의 :code:`FileField` 와 :code:`ImageField` 는 파일과 이미지 파일의 경로를 저장합니다. 이것은 응용 수준에서의 구별이고, 데이터베이스 수준에서는 모두 :code:`CharField` 와 동일한 방식으로 저장됩니다. 파일이 없는 행을 구하려면 다음 코드를 실행하면 됩니다. .. code-block:: python diff --git a/docs/func_expressions.rst b/docs/func_expressions.rst index 139aefe..a3902be 100644 --- a/docs/func_expressions.rst +++ b/docs/func_expressions.rst @@ -5,7 +5,7 @@ 장고가 제공하지 않는 데이터베이스 함수를 실행하기 위해서는 장고의 :code:`Func` 객체를 사용하면 됩니다. -PostgreSQL에는 :code:`fuzzystrmatch` 확장 기능이 있습니다. 이 확장에는 텍스트 데이터의 유사도를 측정하기 위한 함수가 여러 가지 포함되어 있습니다. PostgreSQL 데이터베이스 셸에서 :code:`create extension fuzzystrmatch`를 실행하여 이 확장을 설치하고 아래의 실습을 진행해 주세요. +PostgreSQL에는 :code:`fuzzystrmatch` 확장 기능이 있습니다. 이 확장에는 텍스트 데이터의 유사도를 측정하기 위한 함수가 여러 가지 포함되어 있습니다. PostgreSQL 데이터베이스 셸에서 :code:`create extension fuzzystrmatch` 를 실행하여 이 확장을 설치하고 아래의 실습을 진행해 주세요. 레벤슈타인 치환 거리 알고리즘을 구현한 :code:`levenshtein` 함수를 이용해 보겠습니다. 실습에 사용할 Hero 모델의 항목을 여러 개 생성합시다. @@ -17,7 +17,7 @@ PostgreSQL에는 :code:`fuzzystrmatch` 확장 기능이 있습니다. 이 확장 Hero.objects.create(name="Xeus", description="A greek God", benevolence_factor=80, category_id=12, origin_id=1) Hero.objects.create(name="Poseidon", description="A greek God", benevolence_factor=80, category_id=12, origin_id=1) -이제 :code:`name`이 'Zeus'와 비슷한 :code:`Hero` 항목들을 구해 봅시다. +이제 :code:`name` 이 'Zeus' 와 비슷한 :code:`Hero` 항목들을 구해 봅시다. .. code-block:: python @@ -33,9 +33,9 @@ PostgreSQL에는 :code:`fuzzystrmatch` 확장 기능이 있습니다. 이 확장 function='levenshtein' template="%(function)s(%(expressions)s, 'Zeus')" -이제 :code:`Hero.objects.annotate(like_zeus=LevenshteinLikeZeus(F("name")))`와 같이 클래스를 이용할 수 있습니다. +이제 :code:`Hero.objects.annotate(like_zeus=LevenshteinLikeZeus(F("name")))` 와 같이 클래스를 이용할 수 있습니다. -이렇게 구한 편집 거리 유사도를 기준으로 항목을 선별할 수 있습니다. +이렇게 구한 편집 거리를 기준으로 이름이 비슷한 항목을 선별할 수 있습니다. .. code-block:: ipython diff --git a/docs/generic_models.rst b/docs/generic_models.rst index a1f03af..91f25b9 100644 --- a/docs/generic_models.rst +++ b/docs/generic_models.rst @@ -72,7 +72,7 @@ hero = Hero.objects.create(name='Hades') FlexCategory.objects.create(content_object=hero, name="mythic") -'ghost'로 분류된 :code:`Hero`를 구하려면 다음과 같이 조회합니다. +'ghost'로 분류된 :code:`Hero` 를 구하려면 다음과 같이 조회합니다. .. code-block:: python diff --git a/docs/multiple_databases.rst b/docs/multiple_databases.rst index 0e13c9b..41836f7 100644 --- a/docs/multiple_databases.rst +++ b/docs/multiple_databases.rst @@ -26,7 +26,7 @@ } } -여러 개의 데이터베이스를 함께 사용하려면 데이터베이스 중계기(database router)에 대해 알아야 합니다. 장고의 기본 중계 설정은 데이터베이스를 특정하지 않은 경우 기본 데이터베이스(default database)로 중계하는 것입니다. :code:`DATABASE_ROUTERS` 설정의 기본값은 :code:`[]` 입니다. 중계기는 다음과 같이 정의할 수 있습니다. :: +여러 개의 데이터베이스를 함께 사용하려면 데이터베이스 중계기(database router)에 대해 알아야 합니다. 장고의 기본 중계 설정은 데이터베이스를 특정하지 않은 경우 기본(default) 데이터베이스로 중계하는 것입니다. :code:`DATABASE_ROUTERS` 설정의 기본값은 :code:`[]` 입니다. 중계기는 다음과 같이 정의할 수 있습니다. :: class DemoRouter: """ @@ -66,7 +66,7 @@ return None -위와 같은 중계기가 설정되었을 때, 서로 다른 데이터베이스를 사용하는 모델은 다음과 같이 정의할 수 있습니다. :: +중계기를 위와 같이 설정해 두었으면, 모델이 서로 다른 데이터베이스를 사용하도록 다음과 같이 정의할 수 있습니다. :: class User(models.Model): username = models.Charfield(ax_length=100) @@ -80,6 +80,6 @@ class Meta: app_label = 'customer_data' -여러 개의 데이터베이스를 관리할 때 사용하는 마이그레이션 명령입니다. :: +여러 개의 데이터베이스를 관리할 때 사용하는 마이그레이션 명령도 알아두세요. :: $ ./manage.py migrate --database=users_db diff --git a/docs/multiple_objects.rst b/docs/multiple_objects.rst index ecaad01..c8b29bc 100644 --- a/docs/multiple_objects.rst +++ b/docs/multiple_objects.rst @@ -1,5 +1,5 @@ 여러 개의 행을 한번에 생성하는 방법이 있나요? -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +=================================================================== 여러 개의 신규 객체를 한꺼번에 저장하고 싶은 경우가 있습니다. 예를 들어, 여러 개의 분류 항목을 단번에 생성하되, 데이터베이스에 질의를 여러 번 수행하지 않아야 한다고 합시다. :code:`bulk_create` 메서드를 이용하면 여러 개의 신규 객체를 한 번에 저장할 수 있습니다. diff --git a/docs/notequal_query.rst b/docs/notequal_query.rst index 8223c2f..cfc42d0 100644 --- a/docs/notequal_query.rst +++ b/docs/notequal_query.rst @@ -3,7 +3,7 @@ NOT 연산으로 조건을 부정하려면 어떻게 하나요? .. image:: usertable.png -장고의 사용자 계정 관리 앱인 :code:`django.contrib.auth`를 사용하면 데이터베이스에 :code:`auth_user`이라는 표가 생성됩니다. 이 표에는 :code:`username`, :code:`first_name`, :code:`last_name` 등의 열이 있습니다. +장고의 사용자 계정 관리 앱인 :code:`django.contrib.auth` 를 사용하면 데이터베이스에 :code:`auth_user` 라는 표가 생성됩니다. 이 표에는 :code:`username`, :code:`first_name`, :code:`last_name` 등의 열이 있습니다. id < 5 라는 조건을 만족하지 않는 모든 사용자를 구해 봅시다. 이를 수행하려면 NOT 연산이 필요합니다. diff --git a/docs/null_vs_blank.rst b/docs/null_vs_blank.rst index 503ceae..92dd0e5 100644 --- a/docs/null_vs_blank.rst +++ b/docs/null_vs_blank.rst @@ -1,20 +1,20 @@ -:code:`null=True`와 :code:`blank=True`의 차이가 무엇인가요? +:code:`null=True` 와 :code:`blank=True` 의 차이가 무엇인가요? ==================================================================================================== -:code:`null`와 :code:`blank`는 둘 다 기본값이 :code:`False`입니다. 이 두 설정은 모두 필드(열) 수준에서 동작합니다. 즉, 필드(열)를 비워두는 것을 허용할 것인지를 설정합니다. +:code:`null` 과 :code:`blank` 는 둘 다 기본값이 :code:`False` 입니다. 이 두 설정은 모두 필드(열) 수준에서 동작합니다. 즉, 필드(열)를 비워두는 것을 허용할 것인지를 설정합니다. -:code:`null=True`는 필드의 값이 NULL(정보 없음)로 저장되는 것을 허용합니다. 결국 데이터베이스 열에 관한 설정입니다. :: +:code:`null=True` 는 필드의 값이 NULL(정보 없음)로 저장되는 것을 허용합니다. 결국 데이터베이스 열에 관한 설정입니다. :: date = models.DateTimeField(null=True) -:code:`blank=True`는 필드가 폼(입력 양식)에서 빈 채로 저장되는 것을 허용합니다. 장고 관리자(admin) 및 직접 정의한 폼에도 반영됩니다. :: +:code:`blank=True` 는 필드가 폼(입력 양식)에서 빈 채로 저장되는 것을 허용합니다. 장고 관리자(admin) 및 직접 정의한 폼에도 반영됩니다. :: title = models.CharField(blank=True) # 폼에서 비워둘 수 있음. 데이터베이스에는 ''이 저장됨. -:code:`null=True`와 :code:`blank=True`를 모두 지정하면 어떤 경우로든 비워둘 수 있음을 의미합니다. :: +:code:`null=True` 와 :code:`blank=True` 를 모두 지정하면 어떤 조건으로든 값을 비워둘 수 있음을 의미합니다. :: epic = models.ForeignKey(null=True, blank=True) # 단, CharFields()와 TextFields()에서는 예외입니다. # 장고는 이 경우 NULL을 저장하지 않으며, 빈 값을 빈 문자열('')로 저장합니다. -또 하나 예외적인 경우가 있습니다. 불리언 필드(:code:`BooleanField`)에 NULL을 입력할 수 있도록 하려면 :code:`null=True`를 설정하는 것이 아니라, 널 불리언 필드(:code:`NullBooleanField`)를 사용해야 합니다. \ No newline at end of file +또 하나 예외적인 경우가 있습니다. 불리언 필드(:code:`BooleanField`)에 NULL을 입력할 수 있도록 하려면 :code:`null=True` 를 설정하는 것이 아니라, 널 불리언 필드(:code:`NullBooleanField`)를 사용해야 합니다. \ No newline at end of file diff --git a/docs/numqueries.rst b/docs/numqueries.rst index d229276..5e78baf 100644 --- a/docs/numqueries.rst +++ b/docs/numqueries.rst @@ -1,7 +1,7 @@ 질의 횟수가 고정된 횟수만큼만 일어나는지 확인할 수 있을까요? ======================================================================================= -장고 단위 테스트 클래스의 `assertNumQueries()` 메서드를 사용하여 데이터베이스에 발생하는 질의 횟수를 검증할 수 있습니다. +장고 단위 테스트 클래스의 :code:`assertNumQueries()` 메서드를 사용하여 데이터베이스에 발생하는 질의 횟수를 검증할 수 있습니다. .. code-block:: python diff --git a/docs/one_to_many.rst b/docs/one_to_many.rst index 9635d73..643f3f6 100644 --- a/docs/one_to_many.rst +++ b/docs/one_to_many.rst @@ -41,4 +41,4 @@ ValueError: save() prohibited to prevent data loss due to unsaved related object >>> Article.objects.filter(reporter=u1) , ]> -위 코드에서 구한 쿼리셋을 보면, u1 하나에 여러 개의 :code:`Article`이 연결되어 있음(일대다 관계)을 확인할 수 있습니다. +위 코드에서 구한 쿼리셋을 보면, u1 하나에 여러 개의 :code:`Article` 이 연결되어 있음(일대다 관계)을 확인할 수 있습니다. diff --git a/docs/one_to_one.rst b/docs/one_to_one.rst index cf15cf2..43c3ae6 100644 --- a/docs/one_to_one.rst +++ b/docs/one_to_one.rst @@ -29,8 +29,7 @@ >>> p2.user.last_name 'Upadhyay' -on_delete 메서드는 그 필드에 연결된 항목이 삭제될 때 그 항목을 가리키는 항목들을 어떻게 처리해야 할지 설정합니다. 예를 들어, :code:`on_delete=models.CASCADE`(하위 삭제)는 연결된 항목이 삭제될 때 해당 항목을 함께 삭제하도록 합니다. 따라서, 다음 코드를 실행하면 +on_delete 메서드는 그 필드에 연결된 항목이 삭제될 때 그 항목을 가리키는 항목들을 어떻게 처리해야 할지 설정합니다. 예를 들어, :code:`on_delete=models.CASCADE` (하위 삭제)는 연결된 항목이 삭제될 때 해당 항목을 함께 삭제하도록 합니다. 따라서, 아래의 코드를 실행하면 :code:`User` 모델의 항목(u2) 뿐 아니라 :code:`UserParent`의 항목(p2)도 함께 삭제됩니다. :: >>> u2.delete() -:code:`User` 모델의 항목(u2) 뿐 아니라 :code:`UserParent`의 항목(p2)도 함께 삭제됩니다. diff --git a/docs/or_query.rst b/docs/or_query.rst index 0c8cfc5..5c63757 100644 --- a/docs/or_query.rst +++ b/docs/or_query.rst @@ -3,7 +3,7 @@ OR 연산으로 일부 조건을 하나라도 만족하는 항목을 구하려 .. image:: usertable.png -장고의 사용자 계정 관리 앱인 :code:`django.contrib.auth`를 사용하면 데이터베이스에 :code:`auth_user`이라는 표가 생성됩니다. 이 표에는 :code:`username`, :code:`first_name`, :code:`last_name` 등의 열이 있습니다. +장고의 사용자 계정 관리 앱인 :code:`django.contrib.auth` 를 사용하면 데이터베이스에 :code:`auth_user` 라는 표가 생성됩니다. 이 표에는 :code:`username`, :code:`first_name`, :code:`last_name` 등의 열이 있습니다. :code:`OR` 연산으로 여러 조건 중 하나라도 만족하는 행을 구해야 하는 경우가 많습니다. 이름이 'R'로 시작하거나 성이 'D'로 시작하는 모든 사용자를 구한다고 해 봅시다. diff --git a/docs/order_by_related_model.rst b/docs/order_by_related_model.rst index 69d084e..a3b0d81 100644 --- a/docs/order_by_related_model.rst +++ b/docs/order_by_related_model.rst @@ -14,7 +14,7 @@ name = models.CharField(max_length=100) category = models.ForeignKey(Category, on_delete=models.CASCADE) -아래 코드는 :code:`Hero` 모델의 쿼리셋을 category 필드 순으로 정렬하되, category가 같은 항목은 (:code:`Hero`의) name 필드 순으로 정렬합니다. +아래 코드는 :code:`Hero` 모델의 쿼리셋을 category 필드 순으로 정렬하되, category가 같은 항목은 (:code:`Hero` 의) name 필드 순으로 정렬합니다. .. code-block:: python diff --git a/docs/random.rst b/docs/random.rst index ce5bc1a..1fb0a2b 100644 --- a/docs/random.rst +++ b/docs/random.rst @@ -15,7 +15,7 @@ return self.name -저장된 Category 항목 가운데 하나를 무작위로 구해야 합니다. 두 가지 방법을 살펴보겠습니다. +저장된 :code:`Category` 항목 가운데 하나를 무작위로 구해야 합니다. 두 가지 방법을 살펴보겠습니다. 먼저 살펴볼 방법은 정직하고 이해하기 쉽습니다. :code:`order_by` 메서드로 항목들을 정렬할 때, 정렬 기준을 '무작위'로 지정하는 것입니다. 데이터를 무작위로 정렬하여 첫 번째 항목을 가져오면 무작위 항목을 구할 수 있습니다. 코드로 작성해 봅시다. @@ -24,7 +24,7 @@ def get_random(): return Category.objects.order_by("?").first() -주의: 사용하는 데이터베이스 시스템에 따라 :code:`order_by('?')`의 실행 비용이 비싸고 성능이 느릴 수 있습니다. 뒤이어 살펴볼 다른 방법과의 비교를 위해 :code:`Category` 표에 1백만 개의 항목을 추가해 두겠습니다. 명령행 인터페이스에서 :code:`python manage.py dbshell`를 실행하여 데이터베이스 셸을 열고, 아래 질의문을 실행하시면 실습에 필요한 항목을 준비할 수 있습니다. +주의: 사용하는 데이터베이스 시스템에 따라 :code:`order_by('?')` 의 실행 비용이 비싸고 성능이 느릴 수 있습니다. 뒤이어 살펴볼 다른 방법과의 비교를 위해 :code:`Category` 표에 1백만 개의 항목을 추가해 두겠습니다. 명령행 인터페이스에서 :code:`python manage.py dbshell` 를 실행하여 데이터베이스 셸을 열고, 아래 질의문을 실행하시면 실습에 필요한 항목을 준비할 수 있습니다. .. code-block:: sql @@ -76,7 +76,7 @@ In [10]: get_random3() Out[10]: -삭제된 항목이 많지 않다면 위의 무한반복 구문 :code:`while True:`는 금방 종료될 것입니다. 그러면 파이썬의 :code:`timeit`을 이용해 두 방법의 성능 차이를 확인해 봅시다. +삭제된 항목이 많지 않다면 위의 무한반복 구문 :code:`while True:` 는 금방 종료될 것입니다. 그러면 파이썬의 :code:`timeit` 을 이용해 두 방법의 성능 차이를 확인해 봅시다. .. code-block:: python @@ -86,5 +86,5 @@ In [15]: timeit.timeit(get_random, number=100) Out[15]: 56.92513192095794 -:code:`get_random3`이 :code:`get_random`보다 283배 빠르게 실행되었습니다. 단, :code:`get_random`은 언제나 이용할 수 있는 반면에, :code:`get_random3`의 방법은 장고의 기본 ID 생성 방식(auto increment, 자동 증가)을 재정의한 경우나 삭제된 항목이 너무 많을 때에는 사용하기가 어려울 수 있습니다. +:code:`get_random3` 이 :code:`get_random` 보다 283배 빠르게 실행되었습니다. 단, :code:`get_random` 은 언제나 이용할 수 있는 반면에, :code:`get_random3` 의 방법은 장고의 기본 ID 생성 방식(auto increment, 자동 증가)을 재정의한 경우나 삭제된 항목이 너무 많을 때에는 사용하기가 어려울 수 있습니다. diff --git a/docs/second_largest.rst b/docs/second_largest.rst index 48cff4b..8fb451a 100644 --- a/docs/second_largest.rst +++ b/docs/second_largest.rst @@ -19,7 +19,7 @@ 'Sohan' -:code:`User.objects.order_by('-last_login')[2]`와 같이 쿼리셋에 인덱스 연산을 지시할 때, 장고 ORM은 데이터베이스에서 전체 데이터를 가져온 뒤 인덱싱하는 것이 아니라, :code:`LIMIT ... OFFSET` SQL 구문을 이용해 필요한 데이터만 읽어 옵니다. 실제로 생성되는 SQL 질의문을 살펴봅시다. +:code:`User.objects.order_by('-last_login')[2]` 와 같이 쿼리셋에 인덱스 연산을 지시할 때, 장고 ORM은 데이터베이스에서 전체 데이터를 가져온 뒤 인덱싱하는 것이 아니라, :code:`LIMIT ... OFFSET` SQL 구문을 이용해 필요한 데이터만 읽어 옵니다. 실제로 생성되는 SQL 질의문을 살펴봅시다. .. code-block:: sql diff --git a/docs/select_some_fields.rst b/docs/select_some_fields.rst index 1d08f3e..6510a4f 100644 --- a/docs/select_some_fields.rst +++ b/docs/select_some_fields.rst @@ -1,5 +1,5 @@ 필요한 열만 골라 조회하려면 어떻게 하나요? -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +============================================================================= .. image:: usertable.png @@ -7,8 +7,8 @@ 장고는 두 가지 방법을 제공합니다. -- 쿼리셋의 `values` 메서드와 `values_list` 메서드 -- `only` 메서드 +- 쿼리셋의 :code:`values` 메서드와 :code:`values_list` 메서드 +- :code:`only` 메서드 이름이 R로 시작하는 모든 사용자의 이름(:code:`first_name`)과 성(:code:`last_name`)을 구해 봅시다. 데이터베이스 시스템의 부하를 줄이기 위해 그 외의 열은 가져오지 않겠습니다. @@ -19,7 +19,7 @@ ).values('first_name', 'last_name') >> Category.objects.all().count() 0 -위 코드는 잘 동작합니다. 하지만 TRUNCATE 문이 아니라 :code:`DELETE FROM ...`과 같은 SQL 질의를 수행합니다. 삭제해야 하는 항목의 수가 매우 많은 경우 처리 속도가 느릴 수 있습니다. :code:`truncate` 명령이 필요하다면 다음과 같이 :code:`Category` 모델에 :code:`classmethod`로 추가하면 됩니다. +위 코드는 잘 동작합니다. 하지만 TRUNCATE 문이 아니라 :code:`DELETE FROM ...` 과 같은 SQL 질의를 수행합니다. 삭제해야 하는 항목의 수가 매우 많은 경우 처리 속도가 느릴 수 있습니다. :code:`truncate` 명령이 필요하다면 다음과 같이 :code:`Category` 모델에 :code:`classmethod` 로 추가하면 됩니다. .. code-block:: python @@ -27,4 +27,4 @@ SQL의 TRUNCATE 문은 표에 저장된 모든 항목을 제거하는 명령입 with connection.cursor() as cursor: cursor.execute('TRUNCATE TABLE "{0}" CASCADE'.format(cls._meta.db_table)) -이렇게 메서드를 정의해 두면 :code:`Category.truncate()`를 실행하여 정말로 데이터베이스 시스템에 TRUNCATE 문을 질의할 수 있습니다. +이렇게 메서드를 정의해 두면 :code:`Category.truncate()` 를 실행하여 정말로 데이터베이스 시스템에 TRUNCATE 문을 질의할 수 있습니다. diff --git a/docs/union.rst b/docs/union.rst index f0d672a..f068271 100644 --- a/docs/union.rst +++ b/docs/union.rst @@ -1,5 +1,5 @@ 동일한 모델 또는 서로 다른 모델에서 구한 쿼리셋들을 합할 수 있나요? -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +======================================================================================================================= SQL에서는 여러 개의 결과 집합을 합할 때 UNION 연산을 이용합니다. 장고 ORM에서 union 메서드를 이용해 쿼리셋을 합할 수 있습니다. 합하려는 쿼리셋의 모델이 서로 다른 경우, 각 쿼리셋에 포함된 필드와 데이터 유형이 서로 맞아야 합니다. @@ -32,9 +32,9 @@ SQL에서는 여러 개의 결과 집합을 합할 때 UNION 연산을 이용합 union 메서드는 합하려는 쿼리셋의 필드와 데이터 유형이 서로 일치할 때만 실행할 수 있습니다. 그래서 마지막 명령이 실패했습니다. -:code:`Hero` 모델과 :code:`Villain` 모델은 둘 다 :code:`name` 필드와 :code:`gender` 필드를 갖고 있습니다. :code:`values_list`를 이용해 공통된 필드만 가져온 뒤 union을 수행할 수 있습니다. +:code:`Hero` 모델과 :code:`Villain` 모델은 둘 다 :code:`name` 필드와 :code:`gender` 필드를 갖고 있습니다. :code:`values_list` 를 이용해 공통된 필드만 가져온 뒤 union을 수행할 수 있습니다. -... code-block:: python +.. code-block:: python Hero.objects.all().values_list( "name", "gender" diff --git a/docs/update_denormalized_fields.rst b/docs/update_denormalized_fields.rst index f382a24..5b18a6f 100644 --- a/docs/update_denormalized_fields.rst +++ b/docs/update_denormalized_fields.rst @@ -50,9 +50,9 @@ Hero 모델과 Villain 모델의 항목을 새로 저장할 때, Category 모델 super().save(*args, **kwargs) -위 코드에서 :code:`self.category.hero_count += 1`과 같이 인스턴스의 값을 수정하는 것이 아니라, :code:`update` 메서드로 데이터베이스의 갱신을 수행하도록 한 것을 확인하시기 바랍니다. +위 코드에서 :code:`self.category.hero_count += 1` 과 같이 인스턴스의 값을 수정하는 것이 아니라, :code:`update` 메서드로 데이터베이스의 갱신을 수행하도록 한 것을 확인하시기 바랍니다. -또 다른 방법으로, '시그널'이라는 기능을 이용하는 방법이 있습니다. 시그널을 이용하는 예를 살펴봅시다. +또 다른 방법으로, '시그널(신호)'이라는 기능을 이용하는 방법이 있습니다. 시그널을 이용하는 예를 살펴봅시다. .. code-block:: python @@ -77,6 +77,6 @@ Hero 모델과 Villain 모델의 항목을 새로 저장할 때, Category 모델 :code:`save` 메서드를 재정의하는 방법과 시그널을 이용하는 방법 모두 사용할 수 있습니다. 어느 것을 사용하는 것이 좋을까요? 다음 규칙을 권해 드립니다. -- 반정규화 필드에 영향을 끼치는 모델을 여러분이 통제할 수 있다면 `save` 메서드를 재정의합니다. +- 반정규화 필드에 영향을 끼치는 모델을 여러분이 통제할 수 있다면 :code:`save` 메서드를 재정의합니다. - 반정규화 필드에 영향을 끼치는 모델을 여러분이 통제할 수 없다면(그 영향이 라이브러리 등에서 이루어진다면) 시그널을 이용합니다. diff --git a/docs/uuid.rst b/docs/uuid.rst index 91eb5d4..6c78f69 100644 --- a/docs/uuid.rst +++ b/docs/uuid.rst @@ -3,7 +3,7 @@ 장고에서 모델을 생성하면 ID 필드가 기본 키로 생성됩니다. ID 필드의 기본 데이터 유형은 양의 정수입니다. -양의 정수가 아니라 UUID를 기본 키로 사용하고 싶다면 장고 1.8 버전에서 추가된 :code:`UUIDField`를 사용하면 됩니다. :: +양의 정수가 아니라 UUID를 기본 키로 사용하고 싶다면 장고 1.8 버전에서 추가된 :code:`UUIDField` 를 사용하면 됩니다. :: import uuid from django.db import models From 9a0fdf5c8e886f248fb4d44a9ddb68d74e3a34aa Mon Sep 17 00:00:00 2001 From: Ho Sung Lee Date: Mon, 1 Oct 2018 01:09:03 +0900 Subject: [PATCH 091/100] =?UTF-8?q?NEW:=20PDF=20=EB=B9=8C=EB=93=9C=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EB=B0=8F=20=EC=8A=A4=ED=81=AC=EB=A6=BD?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/conf.py | 4 ++-- docs/pdf_build.sh | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) create mode 100755 docs/pdf_build.sh diff --git a/docs/conf.py b/docs/conf.py index e8005df..36aebe7 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -140,8 +140,8 @@ # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'DjangoORMCookbook.tex', 'Django ORM Cookbook Documentation', - 'Agiliq', 'manual'), + (master_doc, 'DjangoORMCookbook.tex', '장고 ORM 요리책', + 'Agiliq/8퍼센트', 'manual'), ] diff --git a/docs/pdf_build.sh b/docs/pdf_build.sh new file mode 100755 index 0000000..4d0e254 --- /dev/null +++ b/docs/pdf_build.sh @@ -0,0 +1,4 @@ +sphinx-build -b latex . _build/latex +sed -i '' 's/\[T1\]{fontenc}/{kotex}/g' ./_build/latex/DjangoORMCookbook.tex +sed -i '' 's/{babel}/\[english\]{babel}/g' ./_build/latex/DjangoORMCookbook.tex +cd ./_build/latex/ && make all-pdf && cd - From b3d3151b42eb687d874f87e54885e23dbbd4f571 Mon Sep 17 00:00:00 2001 From: Ho Sung Lee Date: Mon, 1 Oct 2018 13:36:54 +0900 Subject: [PATCH 092/100] =?UTF-8?q?CHG:=20=EA=B3=B5=EB=B0=B1=20=EC=97=86?= =?UTF-8?q?=EC=95=A0=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/conf.py b/docs/conf.py index 36aebe7..d3ec77b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -134,6 +134,7 @@ # Latex figure (float) alignment # # 'figure_align': 'htbp', + 'extraclassoptions': 'openany,oneside' } # Grouping the document tree into LaTeX files. List of tuples From 14431b9b47e4c640ede8477bd21afc9252555a06 Mon Sep 17 00:00:00 2001 From: Ho Sung Lee Date: Mon, 1 Oct 2018 13:37:26 +0900 Subject: [PATCH 093/100] =?UTF-8?q?CHG:=20=EB=B6=81=EC=BB=A4=EB=B2=84=20?= =?UTF-8?q?=EC=A0=9C=EC=99=B8=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/pdf_build.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/pdf_build.sh b/docs/pdf_build.sh index 4d0e254..1bf1eeb 100755 --- a/docs/pdf_build.sh +++ b/docs/pdf_build.sh @@ -1,4 +1,6 @@ sphinx-build -b latex . _build/latex sed -i '' 's/\[T1\]{fontenc}/{kotex}/g' ./_build/latex/DjangoORMCookbook.tex sed -i '' 's/{babel}/\[english\]{babel}/g' ./_build/latex/DjangoORMCookbook.tex +sed -i '' '/BookCover/d' ./_build/latex/DjangoORMCookbook.tex + cd ./_build/latex/ && make all-pdf && cd - From 7dfb1c60da757faa56774c71a46b45bdc6b9e9fb Mon Sep 17 00:00:00 2001 From: Ho Sung Lee Date: Mon, 1 Oct 2018 13:41:17 +0900 Subject: [PATCH 094/100] FIX: typo --- docs/subquery.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/subquery.rst b/docs/subquery.rst index 71d0799..c39e23d 100644 --- a/docs/subquery.rst +++ b/docs/subquery.rst @@ -59,7 +59,7 @@ FROM "entities_category" -질의문을 한 단계씩 나누어 살펴봅시다. 다음 코드가 첫 번쨰 단계입니다. +질의문을 한 단계씩 나누어 살펴봅시다. 다음 코드가 첫 번째 단계입니다. .. code-block:: python From 02bcf002c1c8d823e013ad13004ef0ee9584c2f8 Mon Sep 17 00:00:00 2001 From: MinJae Kwon Date: Tue, 2 Oct 2018 10:32:07 +0900 Subject: [PATCH 095/100] Syntax highlighting --- README.md | 375 +++++++++++++++++++++++++++--------------------------- 1 file changed, 190 insertions(+), 185 deletions(-) diff --git a/README.md b/README.md index bdcfd5b..0a5ee25 100644 --- a/README.md +++ b/README.md @@ -15,194 +15,199 @@ #### Events 앱의 모델 +```python +from django.db import models +from django.utils.text import slugify +from entities.models import Hero, Villain +from django.contrib.auth.models import User +import uuid - from django.db import models - from django.utils.text import slugify - from entities.models import Hero, Villain - from django.contrib.auth.models import User - import uuid - - class Epic(models.Model): - name = models.CharField(max_length=255) - participating_heroes = models.ManyToManyField(Hero) - participating_villains = models.ManyToManyField(Villain) - - - class Event(models.Model): - id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) - epic = models.ForeignKey(Epic, on_delete=models.CASCADE) - details = models.TextField() - years_ago = models.PositiveIntegerField() - - - class EventHero(models.Model): - event = models.ForeignKey(Event, on_delete=models.CASCADE) - hero = models.ForeignKey(Hero, on_delete=models.CASCADE) - is_primary = models.BooleanField() - - - class EventVillain(models.Model): - event = models.ForeignKey(Event, on_delete=models.CASCADE) - hero = models.ForeignKey(Villain, on_delete=models.CASCADE) - is_primary = models.BooleanField() - - - class UserParent(models.Model): - user = models.OneToOneField( - User, - on_delete=models.CASCADE, - primary_key=True, - ) - father_name = models.CharField(max_length=100) - mother_name = models.CharField(max_length=100) - - class Article(models.Model): - headline = models.CharField(max_length=100) - pub_date = models.DateField() - reporter = models.ForeignKey(User, on_delete=models.CASCADE, related_name='reporter') - slug = models.SlugField() - - def save(self, *args, **kwargs): - self.slug = slugify(self.headline) - super(Article, self).save(*args, **kwargs) - def __str__(self): - return self.headline - - class Meta: - ordering = ('headline',) - - class TempUser(models.Model): - first_name = models.CharField(max_length=100) - - class Meta: - managed = False - db_table = "temp_user" - - - class ColumnName(models.Model): - a = models.CharField(max_length=40,db_column='column1') - column2 = models.CharField(max_length=50) - - def __str__(self): - return self.a +class Epic(models.Model): + name = models.CharField(max_length=255) + participating_heroes = models.ManyToManyField(Hero) + participating_villains = models.ManyToManyField(Villain) + + +class Event(models.Model): + id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) + epic = models.ForeignKey(Epic, on_delete=models.CASCADE) + details = models.TextField() + years_ago = models.PositiveIntegerField() + + +class EventHero(models.Model): + event = models.ForeignKey(Event, on_delete=models.CASCADE) + hero = models.ForeignKey(Hero, on_delete=models.CASCADE) + is_primary = models.BooleanField() + + +class EventVillain(models.Model): + event = models.ForeignKey(Event, on_delete=models.CASCADE) + hero = models.ForeignKey(Villain, on_delete=models.CASCADE) + is_primary = models.BooleanField() + + +class UserParent(models.Model): + user = models.OneToOneField( + User, + on_delete=models.CASCADE, + primary_key=True, + ) + father_name = models.CharField(max_length=100) + mother_name = models.CharField(max_length=100) + + +class Article(models.Model): + headline = models.CharField(max_length=100) + pub_date = models.DateField() + reporter = models.ForeignKey(User, on_delete=models.CASCADE, related_name='reporter') + slug = models.SlugField() + + def save(self, *args, **kwargs): + self.slug = slugify(self.headline) + super(Article, self).save(*args, **kwargs) + def __str__(self): + return self.headline + + class Meta: + ordering = ('headline',) + + +class TempUser(models.Model): + first_name = models.CharField(max_length=100) + + class Meta: + managed = False + db_table = "temp_user" + + +class ColumnName(models.Model): + a = models.CharField(max_length=40,db_column='column1') + column2 = models.CharField(max_length=50) + + def __str__(self): + return self.a +``` #### Entities 앱의 모델 - from django.db import models - - from django.conf import settings - - - class Category(models.Model): - name = models.CharField(max_length=100) - - class Meta: - verbose_name_plural = "Categories" - - def __str__(self): - return self.name - - - class Origin(models.Model): - name = models.CharField(max_length=100) - - def __str__(self): - return self.name - - - class Entity(models.Model): - GENDER_MALE = "Male" - GENDER_FEMALE = "Female" - GENDER_OTHERS = "Others/Unknown" - - name = models.CharField(max_length=100) - alternative_name = models.CharField( - max_length=100, null=True, blank=True - ) - - - category = models.ForeignKey(Category, on_delete=models.CASCADE) - origin = models.ForeignKey(Origin, on_delete=models.CASCADE) - gender = models.CharField( - max_length=100, - choices=( - (GENDER_MALE, GENDER_MALE), - (GENDER_FEMALE, GENDER_FEMALE), - (GENDER_OTHERS, GENDER_OTHERS), - ) - ) - description = models.TextField() - - added_by = models.ForeignKey(settings.AUTH_USER_MODEL, - null=True, blank=True, on_delete=models.SET_NULL) - added_on = models.DateField(auto_now=True) - - def __str__(self): - return self.name - - class Meta: - abstract = True - - - class Hero(Entity): - - class Meta: - verbose_name_plural = "Heroes" - - is_immortal = models.BooleanField(default=True) - - benevolence_factor = models.PositiveSmallIntegerField( - help_text="How benevolent this hero is?" - ) - arbitrariness_factor = models.PositiveSmallIntegerField( - help_text="How arbitrary this hero is?" - ) - - headshot = models.ImageField(null=True, blank=True, upload_to="hero_headshots/") - - # relationships - father = models.ForeignKey( - "self", related_name="children", null=True, blank=True, on_delete=models.SET_NULL - ) - mother = models.ForeignKey( - "self", related_name="+", null=True, blank=True, on_delete=models.SET_NULL - ) - spouse = models.ForeignKey( - "self", related_name="+", null=True, blank=True, on_delete=models.SET_NULL - ) - - - class HeroProxy(Hero): - - class Meta: - proxy = True - - class Villain(Entity): - is_immortal = models.BooleanField(default=False) - - malevolence_factor = models.PositiveSmallIntegerField( - help_text="How malevolent this villain is?" - ) - power_factor = models.PositiveSmallIntegerField( - help_text="How powerful this villain is?" +```python +from django.db import models + +from django.conf import settings + + +class Category(models.Model): + name = models.CharField(max_length=100) + + class Meta: + verbose_name_plural = "Categories" + + def __str__(self): + return self.name + + +class Origin(models.Model): + name = models.CharField(max_length=100) + + def __str__(self): + return self.name + + +class Entity(models.Model): + GENDER_MALE = "Male" + GENDER_FEMALE = "Female" + GENDER_OTHERS = "Others/Unknown" + + name = models.CharField(max_length=100) + alternative_name = models.CharField( + max_length=100, null=True, blank=True + ) + + category = models.ForeignKey(Category, on_delete=models.CASCADE) + origin = models.ForeignKey(Origin, on_delete=models.CASCADE) + gender = models.CharField( + max_length=100, + choices=( + (GENDER_MALE, GENDER_MALE), + (GENDER_FEMALE, GENDER_FEMALE), + (GENDER_OTHERS, GENDER_OTHERS), ) - is_unique = models.BooleanField(default=True) - count = models.PositiveSmallIntegerField(default=1) - - - class HeroAcquaintance(models.Model): - "Non family contacts of a Hero" - hero = models.OneToOneField(Hero, on_delete=models.CASCADE) - - friends = models.ManyToManyField(Hero, related_name="+") - detractors = models.ManyToManyField(Hero, related_name="+") - main_anatagonists = models.ManyToManyField(Villain, related_name="+") - - - class AllEntity(models.Model): - name = models.CharField(max_length=100) - - class Meta: - managed = False - db_table = "entities_entity" + ) + description = models.TextField() + + added_by = models.ForeignKey(settings.AUTH_USER_MODEL, + null=True, blank=True, on_delete=models.SET_NULL) + added_on = models.DateField(auto_now=True) + + def __str__(self): + return self.name + + class Meta: + abstract = True + + +class Hero(Entity): + + class Meta: + verbose_name_plural = "Heroes" + + is_immortal = models.BooleanField(default=True) + + benevolence_factor = models.PositiveSmallIntegerField( + help_text="How benevolent this hero is?" + ) + arbitrariness_factor = models.PositiveSmallIntegerField( + help_text="How arbitrary this hero is?" + ) + + headshot = models.ImageField(null=True, blank=True, upload_to="hero_headshots/") + + # relationships + father = models.ForeignKey( + "self", related_name="children", null=True, blank=True, on_delete=models.SET_NULL + ) + mother = models.ForeignKey( + "self", related_name="+", null=True, blank=True, on_delete=models.SET_NULL + ) + spouse = models.ForeignKey( + "self", related_name="+", null=True, blank=True, on_delete=models.SET_NULL + ) + + +class HeroProxy(Hero): + + class Meta: + proxy = True + + +class Villain(Entity): + is_immortal = models.BooleanField(default=False) + + malevolence_factor = models.PositiveSmallIntegerField( + help_text="How malevolent this villain is?" + ) + power_factor = models.PositiveSmallIntegerField( + help_text="How powerful this villain is?" + ) + is_unique = models.BooleanField(default=True) + count = models.PositiveSmallIntegerField(default=1) + + +class HeroAcquaintance(models.Model): + "Non family contacts of a Hero" + hero = models.OneToOneField(Hero, on_delete=models.CASCADE) + + friends = models.ManyToManyField(Hero, related_name="+") + detractors = models.ManyToManyField(Hero, related_name="+") + main_anatagonists = models.ManyToManyField(Villain, related_name="+") + + +class AllEntity(models.Model): + name = models.CharField(max_length=100) + + class Meta: + managed = False + db_table = "entities_entity" +``` From a4100a597fc3fd54813ef8b72d5a993af5ba96c9 Mon Sep 17 00:00:00 2001 From: Junghwan Park Date: Tue, 2 Oct 2018 21:19:54 +0900 Subject: [PATCH 096/100] FIX: typo --- docs/one_to_one.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/one_to_one.rst b/docs/one_to_one.rst index 43c3ae6..c2a5584 100644 --- a/docs/one_to_one.rst +++ b/docs/one_to_one.rst @@ -29,7 +29,7 @@ >>> p2.user.last_name 'Upadhyay' -on_delete 메서드는 그 필드에 연결된 항목이 삭제될 때 그 항목을 가리키는 항목들을 어떻게 처리해야 할지 설정합니다. 예를 들어, :code:`on_delete=models.CASCADE` (하위 삭제)는 연결된 항목이 삭제될 때 해당 항목을 함께 삭제하도록 합니다. 따라서, 아래의 코드를 실행하면 :code:`User` 모델의 항목(u2) 뿐 아니라 :code:`UserParent`의 항목(p2)도 함께 삭제됩니다. :: +on_delete 메서드는 그 필드에 연결된 항목이 삭제될 때 그 항목을 가리키는 항목들을 어떻게 처리해야 할지 설정합니다. 예를 들어, :code:`on_delete=models.CASCADE` (하위 삭제)는 연결된 항목이 삭제될 때 해당 항목을 함께 삭제하도록 합니다. 따라서, 아래의 코드를 실행하면 :code:`User` 모델의 항목(u2) 뿐 아니라 :code:`UserParent` 의 항목(p2)도 함께 삭제됩니다. :: >>> u2.delete() From b4fbbe45f6f24cc24487b327308d0304311b4d76 Mon Sep 17 00:00:00 2001 From: Junghwan Park Date: Tue, 2 Oct 2018 22:04:00 +0900 Subject: [PATCH 097/100] FIX: typo --- docs/func_expressions.rst | 2 +- docs/keepdb.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/func_expressions.rst b/docs/func_expressions.rst index a3902be..e569114 100644 --- a/docs/func_expressions.rst +++ b/docs/func_expressions.rst @@ -35,7 +35,7 @@ PostgreSQL에는 :code:`fuzzystrmatch` 확장 기능이 있습니다. 이 확장 이제 :code:`Hero.objects.annotate(like_zeus=LevenshteinLikeZeus(F("name")))` 와 같이 클래스를 이용할 수 있습니다. -이렇게 구한 편집 거리를 기준으로 이름이 비슷한 항목을 선별할 수 있습니다. +이렇게 구한 레벤슈타인 거리를 기준으로 이름이 비슷한 항목을 선별할 수 있습니다. .. code-block:: ipython diff --git a/docs/keepdb.rst b/docs/keepdb.rst index 8bc300f..8018d9b 100644 --- a/docs/keepdb.rst +++ b/docs/keepdb.rst @@ -1,7 +1,7 @@ 데이터베이스를 재사용하여 테스트 실행 속도를 높일 수 있나요? ============================================================================================ -:code:`python manage.py test` 명령을 실행할 때마다 데이터베이스가 새로 생성됩니다. 이것은 마이그레이션이 많지 않을 때는 문제가 되지 않습니다. 하지만 마이그레이션이 많아질 수록 테스트 실행시 데이터베이스 재생성에 많은 시간을 소요하게 됩니다. 이런 상황을 피하기 위해 이전에 생성된 데이터베이스를 재사용할 수 있습니다. +:code:`python manage.py test` 명령을 실행할 때마다 데이터베이스가 새로 생성됩니다. 이것은 마이그레이션이 많지 않을 때는 문제가 되지 않습니다. 하지만 마이그레이션이 많아질수록 테스트 실행 시 데이터베이스 재생성에 많은 시간을 소요하게 됩니다. 이런 상황을 피하기 위해 이전에 생성된 데이터베이스를 재사용할 수 있습니다. 테스트 명령에 :code:`--keepdb` 플래그를 추가하여 데이터베이스가 삭제되는 것을 방지하고 테스트 실행 간 데이터베이스를 유지할 수 있습니다. 데이터베이스가 존재하지 않으면 데이터베이스를 새로 생성합니다. 마지막 테스트 실행 이후 마이그레이션이 추가되었으면 최신 상태를 유지하기 위해 마이그레이션을 수행합니다. From bf0d941a9e669baf2598dfd7bc4a2648ca5f3a2e Mon Sep 17 00:00:00 2001 From: seul lee Date: Sat, 6 Oct 2018 20:48:56 +0900 Subject: [PATCH 098/100] FIX: typo --- docs/or_query.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/or_query.rst b/docs/or_query.rst index 5c63757..585251d 100644 --- a/docs/or_query.rst +++ b/docs/or_query.rst @@ -10,7 +10,7 @@ OR 연산으로 일부 조건을 하나라도 만족하는 항목을 구하려 장고에서는 다음 두 방법으로 구할 수 있습니다. - :code:`queryset_1 | queryset_2` -- :code:`filter(Q()|Q()` +- :code:`filter(Q()|Q())` 질의문 살펴보기 From dbbb321303dcea1d92c0937b219da22ed06ea41f Mon Sep 17 00:00:00 2001 From: seul lee Date: Sat, 6 Oct 2018 21:13:59 +0900 Subject: [PATCH 099/100] =?UTF-8?q?=EA=B9=A8=EC=A7=84=20code=20block=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/notequal_query.rst | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/notequal_query.rst b/docs/notequal_query.rst index cfc42d0..3640610 100644 --- a/docs/notequal_query.rst +++ b/docs/notequal_query.rst @@ -22,11 +22,7 @@ id < 5 라는 조건을 만족하지 않는 모든 사용자를 구해 봅시다 .. image:: sqluser_notquery.png -exclude 메서드를 이용하는 방법은 다음과 같습니다. - -.. code-block - - +exclude 메서드를 이용하는 방법은 다음과 같습니다. :: >>> queryset = User.objects.exclude(id__lt=5) >>> queryset From e7ef16012b66cc1f3d6bd110c80f1d8fd0d7cfd0 Mon Sep 17 00:00:00 2001 From: kyungjunleeme Date: Fri, 11 Feb 2022 21:31:12 +0900 Subject: [PATCH 100/100] =?UTF-8?q?ADD:=20import=20=EB=88=84=EB=9D=BD=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/generic_models.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/generic_models.rst b/docs/generic_models.rst index 91f25b9..612b481 100644 --- a/docs/generic_models.rst +++ b/docs/generic_models.rst @@ -29,7 +29,7 @@ .. code-block:: python - from django.contrib.contenttypes.fields import GenericForeignKey + from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation from django.contrib.contenttypes.models import ContentType # ...