Skip to content

Commit be2f9d2

Browse files
Add: queryset api tutorial code
0 parents  commit be2f9d2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+531557
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# queryset-api

__pycache__/decorators.cpython-38.pyc

977 Bytes
Binary file not shown.

__pycache__/decorators.cpython-39.pyc

981 Bytes
Binary file not shown.

books/__init__.py

Whitespace-only changes.
151 Bytes
Binary file not shown.
155 Bytes
Binary file not shown.
155 Bytes
Binary file not shown.
1.66 KB
Binary file not shown.
1.66 KB
Binary file not shown.
1.66 KB
Binary file not shown.
4.46 KB
Binary file not shown.
4.07 KB
Binary file not shown.
4.51 KB
Binary file not shown.

books/admin.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.contrib import admin
2+
3+
# Register your models here.

books/apps.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from django.apps import AppConfig
2+
3+
4+
class BooksConfig(AppConfig):
5+
name = 'books'
Binary file not shown.
Binary file not shown.

books/management/commands/insert.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import random
2+
3+
from django.core.management.base import BaseCommand
4+
from ...models import Publisher, Store, Book
5+
6+
7+
class Command(BaseCommand):
8+
"""
9+
이 커맨드는 5개의 Publisher, 100개의 books와 10개의 Stores를 DB에 insert합니다.
10+
"""
11+
12+
def handle(self, *args, **options):
13+
Publisher.objects.all().delete()
14+
Book.objects.all().delete()
15+
Store.objects.all().delete()
16+
17+
# create 5 publishers
18+
publishers = [Publisher(name=f"Publisher{index}") for index in range(1, 20)]
19+
Publisher.objects.bulk_create(publishers)
20+
21+
# create 20 books for every publishers
22+
counter = 0
23+
books = []
24+
for publisher in Publisher.objects.all():
25+
for i in range(1000):
26+
counter = counter + 1
27+
books.append(Book(name=f"Book{counter}", price=random.randint(50, 300), publisher=publisher))
28+
29+
Book.objects.bulk_create(books)
30+
31+
# create 10 stores and insert 10 books in every store
32+
books = list(Book.objects.all())
33+
for i in range(1000):
34+
temp_books = [books.pop(0) for i in range(10)]
35+
store = Store.objects.create(name=f"Store{i+1}")
36+
store.books.set(temp_books)
37+
store.save()

books/migrations/0001_initial.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Generated by Django 3.1.2 on 2020-11-25 02:06
2+
3+
from django.db import migrations, models
4+
import django.db.models.deletion
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
initial = True
10+
11+
dependencies = [
12+
]
13+
14+
operations = [
15+
migrations.CreateModel(
16+
name='Book',
17+
fields=[
18+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19+
('name', models.CharField(max_length=255)),
20+
('price', models.IntegerField(default=0)),
21+
],
22+
),
23+
migrations.CreateModel(
24+
name='Publisher',
25+
fields=[
26+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
27+
('name', models.CharField(max_length=255)),
28+
],
29+
),
30+
migrations.CreateModel(
31+
name='Store',
32+
fields=[
33+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
34+
('name', models.CharField(max_length=255)),
35+
('books', models.ManyToManyField(to='books.Book')),
36+
],
37+
),
38+
migrations.AddField(
39+
model_name='book',
40+
name='publisher',
41+
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='books.publisher'),
42+
),
43+
]
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Generated by Django 3.1.2 on 2020-11-25 05:12
2+
3+
from django.db import migrations
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('books', '0001_initial'),
10+
]
11+
12+
operations = [
13+
migrations.AlterModelTable(
14+
name='book',
15+
table='books',
16+
),
17+
migrations.AlterModelTable(
18+
name='publisher',
19+
table='publishers',
20+
),
21+
migrations.AlterModelTable(
22+
name='store',
23+
table='stores',
24+
),
25+
]

books/migrations/__init__.py

Whitespace-only changes.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

books/models.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from django.db import models
2+
3+
class Publisher(models.Model):
4+
name = models.CharField(max_length=255)
5+
6+
class Meta:
7+
db_table = 'publishers'
8+
9+
def __str__(self):
10+
return self.name
11+
12+
13+
class Book(models.Model):
14+
name = models.CharField(max_length=255)
15+
price = models.IntegerField(default=0)
16+
publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)
17+
18+
class Meta:
19+
db_table = 'books'
20+
21+
def __str__(self):
22+
return self.name
23+
24+
25+
class Store(models.Model):
26+
name = models.CharField(max_length=255)
27+
books = models.ManyToManyField(Book)
28+
29+
class Meta:
30+
db_table = 'stores'
31+
32+
def __str__(self):
33+
return self.name

books/tests.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.test import TestCase
2+
3+
# Create your tests here.

books/views.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
from django.views import View
2+
from .models import Book, Store
3+
from django.http import JsonResponse
4+
from decorators import query_debugger
5+
from django.db.models import Prefetch
6+
7+
class BooksWithAllMethodView(View):
8+
@query_debugger
9+
def get(self, request):
10+
print('Book에서 Publisher Instance에 접근하는 경우 <정참조>')
11+
queryset = Book.objects.all()
12+
books = []
13+
for book in queryset:
14+
books.append({
15+
'id': book.id,
16+
'name': book.name,
17+
'publisher': book.publisher.name # book.publisher에 접근, 캐싱되지 않은 데이터이므로 query 발생
18+
}
19+
)
20+
return JsonResponse({'books_with_all_method' : books }, status=200)
21+
22+
class BooksWithSelectRelatedView(View):
23+
@query_debugger
24+
def get(self, request):
25+
print('Book에서 Publisher Instance에 접근하는 경우 <정참조>')
26+
queryset = Book.objects.select_related("publisher").all()
27+
books = []
28+
for book in queryset:
29+
books.append({
30+
'id': book.id,
31+
'name': book.name,
32+
'publisher': book.publisher.name
33+
}
34+
)
35+
return JsonResponse({'books_with_all_method' : books }, status=200)
36+
37+
38+
# Store(1) : Book(M)
39+
# Store에서 Book Instance에 접근하는 경우 <역참조>
40+
class StoresWithAllMethodView(View):
41+
@query_debugger
42+
def get(self, request):
43+
print(f'Store에서 Book Instance에 접근하는 경우 <역참조>')
44+
queryset = Store.objects.all()
45+
stores = []
46+
for store in queryset:
47+
books = [book.name for book in store.books.all()]
48+
stores.append({
49+
'id': store.id,
50+
'name': store.name,
51+
'books': books
52+
}
53+
)
54+
return JsonResponse({'stores_with_all_method' : stores }, status=200)
55+
56+
class StoresWithPrefetchRelatedView(View):
57+
@query_debugger
58+
def get(self, request):
59+
print(f'Store에서 Book Instance에 접근하는 경우 <역참조>')
60+
queryset = Store.objects.prefetch_related("books").all()
61+
stores = []
62+
for store in queryset:
63+
books = [book.name for book in store.books.all()]
64+
stores.append({'id': store.id, 'name': store.name, 'books': books})
65+
66+
return JsonResponse({'stores_with_prefetch_related' : stores }, status=200)
67+
68+
69+
class StoresWithPrefetchNoneObjectView(View):
70+
@query_debugger
71+
def get(self, request):
72+
print(f'Store에서 Book Instance에 접근하는 경우 <역참조>')
73+
queryset = Store.objects.prefetch_related("books").all()
74+
stores = []
75+
for store in queryset:
76+
books = [book.name for book in store.books.filter(name='Book1')]
77+
stores.append({'id': store.id, 'name': store.name, 'books': books})
78+
79+
return JsonResponse({'stores_with_prefetch_related' : stores }, status=200)
80+
81+
class StoresWithPrefetchObjectView(View):
82+
@query_debugger
83+
def get(self, request):
84+
print(f'Store에서 Book Instance에 접근하는 경우 <역참조>')
85+
queryset = Store.objects.prefetch_related(Prefetch('books', queryset=Book.objects.filter(name='Book1')))
86+
stores = []
87+
for store in queryset:
88+
books = [book.name for book in store.books.all()]
89+
stores.append({'id': store.id, 'name': store.name, 'books': books})
90+
91+
return JsonResponse({'stores_with_prefetch_related' : stores }, status=200)
92+
93+
94+
class StoresWithPrefetchObjectView(View):
95+
@query_debugger
96+
def get(self, request):
97+
print(f'Store에서 Book Instance에 접근하는 경우 <역참조>')
98+
queryset = Store.objects.prefetch_related(Prefetch('books', queryset=Book.objects.filter(name='Book1'), to_attr='book1_list'))
99+
stores = []
100+
for store in queryset:
101+
books = [book.name for book in store.book1_list]
102+
stores.append({'id': store.id, 'name': store.name, 'books': books})
103+
104+
return JsonResponse({'stores_with_prefetch_related' : stores }, status=200)
105+

db.sqlite3

1.52 MB
Binary file not shown.

0 commit comments

Comments
 (0)