๐Ÿค  ์žฅ๊ณ  ์ฟผ๋ฆฌ์…‹ (Queryset ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ดํ•˜๋Š” ๋ฉ”์†Œ๋“œ)

42199 ๋‹จ์–ด ์žฅ๊ณ ์žฅ๊ณ 

์žฅ๊ณ  ์ฟผ๋ฆฌ์…‹์„ ์ •๋ณตํ•ด๋ณด์ž.

๐Ÿ™‹โ€โ™€๏ธ QuerySet API reference

ํ•ด๋‹น ํŠœํ† ๋ฆฌ์–ผ์„ ์ง„ํ–‰ํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋˜๋Š” ๋ชจ๋ธ์€ ์•„๋ž˜์™€ ๊ฐ™์ด ์ •์˜๋œ๋‹ค.
Blog, Author, Entry 3๊ฐœ์˜ ํ•„๋“œ๋กœ ๊ตฌ์„ฑ๋˜์–ด์žˆ๋‹ค.

class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    def __str__(self):
        return self.name

class Author(models.Model):
    name = models.CharField(max_length=200)
    email = models.EmailField()

    def __str__(self):
        return self.name

class Entry(models.Model):
    blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
    headline = models.CharField(max_length=255)
    body_text = models.TextField()
    pub_date = models.DateField()
    mod_date = models.DateField()
    authors = models.ManyToManyField(Author)
    number_of_comments = models.IntegerField()
    number_of_pingbacks = models.IntegerField()
    rating = models.IntegerField()

    def __str__(self):
        return self.headline

๐Ÿงช ์ฟผ๋ฆฌ์…‹์€ ์–ธ์ œ ํ‰๊ฐ€ ๋˜๋Š”๊ฐ€?

์žฅ๊ณ  ์ฟผ๋ฆฌ์…‹์€ ๋ฐ”๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ฟผ๋ฆฌ๋ฌธ์„ ๋‚ ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค.
๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—ฐ์‚ฐ์„ ํ•  ๋•Œ ์‹ค์ œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ฟผ๋ฆฌ๋ฌธ์„ ๋‚ ๋ฆฌ๊ฒŒ ๋œ๋‹ค.

  • Iteration
  • Slicing
  • Pickling/ Cashing
  • repr()
  • len()
  • list()
  • bool()

๐Ÿ’ฝ Queryset API


๐Ÿš€ Queryset ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ดํ•˜๋Š” ๋ฉ”์†Œ๋“œ


filter()

  • filter(**kwargs)

ํ‚ค์›Œ๋“œ ์ธ์ˆ˜๋กœ ๋„˜๊ฒจ์ค€ ์กฐ๊ฑด์— ๋งž๋Š” ์ฟผ๋ฆฌ์…‹์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

In [7]: Blog.objects.filter(id=1)
Out[7]: <QuerySet [<Blog: hi>]>

์กฐ๊ฑด์„ ๋‘๊ฐ€์ง€๋ฅผ ์ค˜์„œ AND ์—ฐ์‚ฐ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

In [16]: Blog.objects.filter(id=1, name="hi")
Out[16]: <QuerySet [<Blog: hi>]>
  • sql ์ฟผ๋ฆฌ๋ฌธ
mysql> select * from blogs_blog where id=1 and name="hi";
+----+------+---------+
| id | name | tagline |
+----+------+---------+
|  1 | hi   | hello   |
+----+------+---------+

exclude()

  • exclude(**kwargs)

ํ‚ค์›Œ๋“œ ์ธ์ˆ˜๋กœ ๋„˜๊ฒจ์ค€ ์กฐ๊ฑด์— ๋งž์ง€'์•Š์€' ์ฟผ๋ฆฌ์…‹์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

In [10]: Blog.objects.all()
Out[10]: <QuerySet [<Blog: hi>, <Blog: hello>]>

In [12]: Blog.objects.exclude(id=1)
Out[12]: <QuerySet [<Blog: hello>]>

์กฐ๊ฑด์„ ๋‘๊ฐ€์ง€๋ฅผ ์ค˜์„œ AND ์—ฐ์‚ฐ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

In [18]: Blog.objects.exclude(id=1, name="hi")
Out[18]: <QuerySet [<Blog: hello>]>
  • sql ์ฟผ๋ฆฌ๋ฌธ
mysql> select * from blogs_blog where not (id=1) and not (name="hi");
+----+-------+---------+
| id | name  | tagline |
+----+-------+---------+
|  2 | hello | world   |
+----+-------+---------+

annotate()

  • annotate(*args, **kwargs)

.annotate()์˜ ๊ฐ ์ธ์ˆ˜๋Š” QuerySet์˜ ๊ฐ ๊ฐ์ฒด์— ์ถ”๊ฐ€ ๋  ์ฃผ์„์ด๋‹ค. ์ฃผ์„๋“ค์€ ๋‹จ์ˆœํ•œ ๊ฐ’, ๋ชจ๋ธ์˜ ํ•„๋“œ์— ๋Œ€ํ•œ ์ฐธ์กฐ, QuerySet์˜ ๊ฐ ๊ฐ์ฒด์™€ ๊ด€๋ จ๋œ ์ง‘๊ณ„(averages, sums ๋“ฑ)์ด๋‹ค.
์ƒˆ๋กœ์šด ์š”์†Œ๋ฅผ ๋ฐ์ดํ„ฐ ์ฟผ๋ฆฌ์— ์ถ”๊ฐ€ํ•˜๊ณ  ํ•ด๋‹น ์š”์†Œ๋ฅผ ๋”ฐ๋กœ ์ถœ๋ ฅํ•ด๋ณผ ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋Š” ๊ฒƒ์ธ๋ฐ, ๋ฐ์ดํ„ฐ๊ฐ€ ๋ช‡ ๊ฐœ ์กด์žฌํ•˜๋Š”์ง€๋ฅผ .count()๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด์„œ annotateํ•ด์ฃผ๊ณ  ์ด๋ฅผ __count๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

์‰ฝ๊ฒŒ ๋งํ•ด์„œ .annotate()๋Š” ํ•„๋“œ ํ•˜๋‚˜๋ฅผ ๋งŒ๋“ค๊ณ  ๊ฑฐ๊ธฐ์— '์–ด๋–ค ๋‚ด์šฉ' ์„ ์ฑ„์šฐ๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด๋‹ค. ์—‘์…€์—์„œ ์ปฌ๋Ÿผ ํ•˜๋‚˜๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ๊ณผ ๊ฐ™๋‹ค๊ณ  ๋ณด๋ฉด ๋œ๋‹ค. ๋‚ด์šฉ์—๋Š” 1. ๋‹ค๋ฅธ ํ•„๋“œ์˜ ๊ฐ’์„ ๊ทธ๋Œ€๋กœ ๋ณต์‚ฌํ•˜๊ฑฐ๋‚˜, 2. ๋‹ค๋ฅธ ํ•„๋“œ์˜ ๊ฐ’๋“ค์„ ์กฐํ•ฉํ•œ ๊ฐ’์„ ๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค.
์ถœ์ฒ˜

์ถ”๊ฐ€ ์‚ฌ์šฉ๋ฒ• ์ •๋ฆฌ ๋งํฌ: ์–ด๋…ธํ…Œ์ดํŠธ ๊ธฐ๋Šฅ

sql์˜ GroupBy ๊ธฐ๋Šฅ๊ณผ ๊ฐ™๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.


order_by()

  • order_by(*fields)

์ฟผ๋ฆฌ์…‹์— oreder_by๋ฉ”์†Œ๋“œ์˜ ์ธ์ž๋กœ ๋„ฃ์–ด์ค€ ํ•„๋“œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌํ•œ๋‹ค.

In [35]: Blog.objects.all()
Out[35]: <QuerySet [<Blog: hi>, <Blog: hello>, <Blog: bro>, <Blog: why?>]>

In [33]: Blog.objects.all().order_by('id')
Out[33]: <QuerySet [<Blog: hi>, <Blog: hello>, <Blog: bro>, <Blog: why?>]>

In [34]: Blog.objects.all().order_by('-id')
Out[34]: <QuerySet [<Blog: why?>, <Blog: bro>, <Blog: hello>, <Blog: hi>]>

order_by('ํ•„๋“œ'): ์˜ค๋ฆ„์ฐจ์ˆœ
order_by('-ํ•„๋“œ'): ๋‚ด๋ฆผ์ฐจ์ˆœ

  • sql ์ฟผ๋ฆฌ๋ฌธ

mysql> select * from blogs_blog order by id ASC;
+----+-------+---------+
| id | name  | tagline |
+----+-------+---------+
|  1 | hi    | hello   |
|  2 | hello | world   |
|  3 | bro   | hello   |
|  4 | why?  | hello   |
+----+-------+---------+

mysql> select * from blogs_blog order by id DESC;
+----+-------+---------+
| id | name  | tagline |
+----+-------+---------+
|  4 | why?  | hello   |
|  3 | bro   | hello   |
|  2 | hello | world   |
|  1 | hi    | hello   |
+----+-------+---------+

values()

  • values(*fields, **expressions)

์ฟผ๋ฆฌ์…‹ ๊ฒฐ๊ณผ๋ฅผ ๋”•์…”๋„ˆ๋ฆฌ ํ˜•ํƒœ๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

In [63]: a
Out[63]: <QuerySet [{'id': 1, 'name': 'hi', 'tagline': 'hello'}, {'id': 2, 'name': 'hello', 'tagline': 'world'}, {'id': 3, 'name': 'bro', 'tagline': 'hello'}, {'id': 4, 'name': 'why?', 'tagline': 'hello'}, {'id': 5, 'name': 'hi', 'tagline': 'what?'}]>

In [64]: a[0]
Out[64]: {'id': 1, 'name': 'hi', 'tagline': 'hello'}

values_list()

  • values_list(*fields, flat=False, named=False)

์ฟผ๋ฆฌ์…‹์˜ ๊ฐ’์„ ํŠœํ”Œ ํ˜•ํƒœ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

In [65]: Blog.objects.all().values_list()
Out[66]: <QuerySet [(1, 'hi', 'hello'), (2, 'hello', 'world'), (3, 'bro', 'hello'), (4, 'why?', 'hello'), (5, 'hi', 'what?')]>

In [68]: Blog.objects.all().values_list('name')
Out[69]: <QuerySet [('hi',), ('hello',), ('bro',), ('why?',), ('hi',)]>

In [70]: Blog.objects.all().values_list('id','name')
Out[71]: <QuerySet [(1, 'hi'), (2, 'hello'), (3, 'bro'), (4, 'why?'), (5, 'hi')]>

union()

์ฟผ๋ฆฌ์…‹์„ ํ•ฉ์น  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

In [72]: a = Blog.objects.filter(id=1)

In [73]: a
Out[73]: <QuerySet [<Blog: hi>]>

In [74]: b = Blog.objects.filter(id=2)

In [75]: b
Out[75]: <QuerySet [<Blog: hello>]>

In [76]: result = a.union(b)

In [77]: result
Out[77]: <QuerySet [<Blog: hi>, <Blog: hello>]>

select_related()

  • select_related(*fields)

sql์˜ ์กฐ์ธ๋ฌธ ์—ญํ• ์„ ํ•œ๋‹ค.
slecected_related๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ ๊ฒŒ ๊ฑด๋“œ๋ฆฐ๋‹ค.

# ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค๋ฅผ ๊ฑด๋“œ๋ฆฐ๋‹ค.
e = Entry.objects.get(id=5)

# ๋˜ ๊ฑด๋“œ๋ฆฐ๋‹ค. 
b = e.blog

select_related ์‚ฌ์šฉ

# ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค๋ฅผ ๊ฑด๋“œ๋ฆฐ๋‹ค.
e = Entry.objects.select_related('blog').get(id=5)

# ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์•ˆ๊ฑด๋“œ๋ฆฐ๋‹ค. 
b = e.blog
  • sql ์ฟผ๋ฆฌ๋ฌธ
mysql> select b.*, e.* from blogs_blog as b join blogs_entry as e on b.id = e.id;
+----+-------+---------+----+----------+-----------------+------------+------------+--------------------+---------------------+--------+---------+
| id | name  | tagline | id | headline | body_text       | pub_date   | mod_date   | number_of_comments | number_of_pingbacks | rating | blog_id |
+----+-------+---------+----+----------+-----------------+------------+------------+--------------------+---------------------+--------+---------+
|  1 | hi    | hello   |  1 | lalala   | ์•ˆ๋…•ํ•˜์„ธ์š”      | 2021-08-14 | 2021-08-14 |                  1 |                   1 |      1 |       1 |
|  2 | hello | world   |  2 | lhahaha  | ji hello        | 2021-08-14 | 2021-08-14 |                  1 |                   3 |      2 |       2 |
+----+-------+---------+----+----------+-----------------+------------+------------+--------------------+---------------------+--------+---------+
2 rows in set (0.00 sec)

์ข‹์€ ์›นํŽ˜์ด์ง€ ์ฆ๊ฒจ์ฐพ๊ธฐ