๐Ÿฆ๋ฉ‹์Ÿ์ด ์‚ฌ์ž์ฒ˜๋Ÿผ 11๊ธฐ/๋ฐฑ์—”๋“œ๋ฅผ ์œ„ํ•œ Django Rest Framework

Chapter6 ์‹ค์ „ ํ”„๋กœ์ ํŠธ! Django REST Framework + React.js ๊ฒŒ์‹œํŒ ๋งŒ๋“ค๊ธฐ -2

1son 2023. 5. 18. 17:46
์ด ๊ฒŒ์‹œ๊ธ€์€ ๋ฉ‹์Ÿ์ด ์‚ฌ์ž์ฒ˜๋Ÿผ ๋™์•„๋ฆฌ์˜ ์žฅ๊ณ  ์Šคํ„ฐ๋””๋ฅผ ์œ„ํ•ด ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค. 

 

- ์ฑ… ๋ฐฑ์—”๋“œ๋ฅผ ์œ„ํ•œ DJANGO REST FRAMEWORK with ํŒŒ์ด์ฌ - ๊ถŒํƒœํ˜• ์ €์ž ์˜ ์ฑ…์„ ์ฐธ๊ณ ํ•˜์—ฌ ์‹ค์Šต์„ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

๋ฐฑ์—”๋“œ๋ฅผ ์œ„ํ•œ Django REST Framework with ํŒŒ์ด์ฌ

COUPANG

www.coupang.com

 

 

6.2.7 (TIP) ๋ฆฌ์•กํŠธ์™€ ์—ฐ๋™ํ•˜๊ธฐ

CORS๋Š” ์–ด๋–ค ๊ฐœ๋…์ผ๊นŒ? -> ์‰ฝ๊ฒŒ ๋‹จ์–ด ๋œป์„ ํ’€์–ด๋ณด๋ฉด, 

๋‹ค๋ฅธ ์ถœ์ฒ˜๋ผ๋ฆฌ ์ž์›์„ ๊ณต์œ ํ•˜๋Š” ๊ฒƒ

 

๊ฐ™์€ ์ถœ์ฒ˜๋ผ๋Š” ๊ฒƒ์€ ์ฃผ์†Œ๊ฐ’์ด ํฌํŠธ ๋ฒˆํ˜ธ๊นŒ์ง€ ๋™์ผํ•œ ๊ฒฝ์šฐ๋ฅผ ๋œปํ•ฉ๋‹ˆ๋‹ค. 

์ฆ‰, ๋ฆฌ์•กํŠธ ํ”„๋กœ์ ํŠธ์™€ Django ํ”„๋กœ์ ํŠธ๋ฅผ ์—ฐ๋™ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ 

๋ฆฌ์•กํŠธ๋Š” http://127.0.0.1:3000, Django ํ”„๋กœ์ ํŠธ๋Š” http://127.0.0.1:8000์ด๋ฏ€๋กœ 

 

-> ํฌํŠธ๋ฒˆํ˜ธ๊ฐ€ ๋‹ฌ๋ผ ๋‹ค๋ฅธ ์ถœ์ฒ˜๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. 

๋ฆฌ์•กํŠธ์—์„œ ๋‹ค๋ฅธ ์ถœ์ฒ˜์ธ Django ๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ(๋ฆฌ์†Œ์Šค)๋ฅผ ๊ฐ€์ ธ์˜ค๋ ค๋Š”๋ฐ

์ด๊ฒƒ์ด SOP(Same Origin Policy)_๊ฒฝ์ฐฐ?์— ์˜ํ•ด

์ฐจ๋‹จ ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. 

 

์ด์— ๋Œ€ํ•œ ์˜ˆ์™ธ ์กฐํ•ญ์ด CORS ์ž…๋‹ˆ๋‹ค. 

 

CORS์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์•„๋ž˜ ๋งํฌ ์ฐธ๊ณ 

 

CORS๋Š” ์™œ ์ด๋ ‡๊ฒŒ ์šฐ๋ฆฌ๋ฅผ ํž˜๋“ค๊ฒŒ ํ•˜๋Š”๊ฑธ๊นŒ?

์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” ์›น ๊ฐœ๋ฐœ์ž๋ผ๋ฉด ํ•œ๋ฒˆ์ฏค์€ ์–ป์–ด๋งž์•„ ๋ดค์„ ๋ฒ•ํ•œ ์ •์ฑ…์— ๋Œ€ํ•œ ์ด์•ผ๊ธฐ๋ฅผ ํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค. ์‚ฌ์‹ค ์›น ๊ฐœ๋ฐœ์„ ํ•˜๋‹ค๋ณด๋ฉด CORS ์ •์ฑ… ์œ„๋ฐ˜์œผ๋กœ ์ธํ•ด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์ƒํ™ฉ์€ ๊ต‰์žฅํžˆ ํ”ํ•ด์„œ

evan-moon.github.io

 

 


์ฆ‰, ์„œ๋ฒ„์—์„œ (๋ฐฑ์—”๋“œ์—์„œ ) CORS ์ •์ฑ…์„ ์ค€์ˆ˜ํ•˜๋„๋ก ์„ค์ •ํ•ด๋‘๋ฉด

SOP์˜ ์˜ˆ์™ธ ์กฐํ•ญ์ธ CORS ์ •์ฑ…์„ ์ค€์ˆ˜ํ•˜์—ฌ

๋‹ค๋ฅธ ์ถœ์ฒ˜๋ผ๋ฆฌ๋„ ์ž์› ๊ณต์œ ๊ฐ€ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

(ํ”„๋ก ํŠธ์—”๋“œ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์—๋Ÿฌ์ง€๋งŒ ๋ฐฑ์—”๋“œ์—์„œ ์ •์ฑ…์„ ์ง€์ผœ์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ด ์กฐ๊ธˆ ์•„์ด๋Ÿฌ๋‹ˆํ•œ ๋ถ€๋ถ„์ž„๋‹ค)

 

์ž ๊ทธ๋Ÿผ ์ด์ œ, ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

1. ํŒจํ‚ค์ง€ ์„ค์น˜ 

2. ์•ฑ์— ๋“ฑ๋ก

 

3. ๋ฏธ๋“ค์›จ์–ด์— ๋“ฑ๋ก

์ด์ œ ๋ฐฑ์—”๋“œ๊ฐ€ ํ•  ์ผ์€ ์—†์Šต๋‹ˆ๋‹ค. 

 

ํ”„๋ก ํŠธ์—”๋“œ์—์„œ ์–ด๋–ป๊ฒŒ ์šฐ๋ฆฌ์˜ ๋ฐฑ์—”๋“œ API๋ฅผ ๊ฐ€์ ธ๋‹ค ์“ฐ๋Š”์ง€ ํ™•์ธํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. 

๋ฆฌ์•กํŠธ์˜ ํ•ต์‹ฌ์ ์ธ ๋ถ€๋ถ„์˜ ์ฝ”๋“œ๋งŒ ์‚ดํŽด๋ณด๊ณ  ์ ์šฉ๋œ ๊ฒฐ๊ณผ ํ™”๋ฉด์„ ํ•จ๊ป˜ ์‚ดํŽด๋ณด๋ฉฐ ๋งˆ๋ฌด๋ฆฌ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. 

 

 

6.3 ์•ฑ : ๊ฒŒ์‹œ๊ธ€

๊ฒŒ์‹œ๊ธ€ ์•ฑ์„ ๋งŒ๋“ค๊ณ  ๊ฒŒ์‹œ๊ธ€ ๊ด€๋ จ ๊ธฐ๋Šฅ์„ ๊ฐœ๋ฐœํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

6.3.1 ๊ฒŒ์‹œ๊ธ€ ๊ธฐ๋Šฅ ์ •๋ฆฌ

์‚ฌ์‹ค ์•ž์„œ ์ง„ํ–‰ํ•œ ํšŒ์› ๊ด€๋ จ ๊ธฐ๋Šฅ์ด ํ”„๋กœ์ ํŠธ์—์„œ ์ œ์ผ ์–ด๋ ต๊ณ  ๋‚ฎ์„  ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. 

 

6.3.2 ๊ฒŒ์‹œ๊ธ€ ๋ชจ๋ธ ๋งŒ๋“ค๊ธฐ & ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜

posts ๋ผ๋Š” ์ด๋ฆ„์˜ ์•ฑ์„ ๋งŒ๋“ค๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋ชจ๋ธ์„ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. 

์ €์ž, ์ €์ž ํ”„๋กœํ•„, ์ œ๋ชฉ, ์นดํ…Œ๊ณ ๋ฆฌ, ๋ณธ๋ฌธ, ์ด๋ฏธ์ง€, ์ข‹์•„์š” ๋ˆ„๋ฅธ ์‚ฌ๋žŒ๋“ค, ๊ธ€์ด ์˜ฌ๋ผ๊ฐ„ ์‹œ๊ฐ„

 

๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์— ์„ฑ๊ณตํ•จ

 

6.3.3 ์‹œ๋ฆฌ์–ผ๋ผ์ด์ €

๋ชจ๋ธ์˜ ๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ ์‹œ๋ฆฌ์–ผ๋ผ์ด์ €์ž…๋‹ˆ๋‹ค.

๊ฐ™์€ ๋ชจ๋ธ์— ๋Œ€ํ•ด ๋‘ ๊ฐœ์˜ ์‹œ๋ฆฌ์–ผ๋ผ์ด์ €๋ฅผ ๋งŒ๋“ค ๊ฒƒ

์ผ๋‹จ ์ž‘์„ฑํ•˜๊ณ , ์™œ ๊ทธ๋ ‡๊ฒŒ ํ–ˆ๋Š”์ง€ ์ดํ•ดํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

-> ๊ฐ์ž ์šฉ๋„๊ฐ€ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ 

-> ๊ฒŒ์‹œ๊ธ€์„ ์ž‘์„ฑํ•  ๋•Œ, ์œ ์ €๊ฐ€ ์ž…๋ ฅํ•ด์ฃผ๋Š” ์ •๋ณด๋Š” ์ œ๋ชฉ, ์นดํ…Œ๊ณ ๋ฆฌ, ๋ณธ๋ฌธ, ์ด๋ฏธ์ง€ ์ •๋„ ๋ฟ,,, ๋‚˜๋จธ์ง€ ๋ฐ์ดํ„ฐ๋Š” ์šฐ๋ฆฌ์˜ ์ฝ”๋“œ๊ฐ€ ์•Œ์•„์„œ  ์ฑ„์›Œ์ฃผ๊ฑฐ๋‚˜, ์ฒ˜์Œ์—๋Š” ๋นˆ์นธ์œผ๋กœ ๋‘๊ฒŒ ๋˜๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. 

-> ์ด๋Ÿฐ ๊ฒฝ์šฐ ํ•ด๋‹น ๊ฒŒ์‹œ๊ธ€์— ๋Œ€ํ•œ ๋ชจ๋“  ์ •๋ณด๋ฅผ ์—ญ์œผ๋กœ JSON์œผ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์ „๋‹ฌํ•ด์•ผ ํ•˜๋Š” ์‹œ๋ฆฌ์–ผ๋ผ์ด์ €์™€๋Š” ๋ถ„๋ช… ๋‹ค๋ฅผ ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

-> ๋”ฐ๋ผ์„œ ์ผ๋ฐ˜ PostSerializer์™€ PostCreateSerializer๋ฅผ ๋‚˜๋ˆ  ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค. 

 

 

6.3.4 ๋ทฐ(CRUD) + ๊ถŒํ•œ

๋‹ค์Œ์€ ๋ทฐ ์ž…๋‹ˆ๋‹ค. ๊ฒŒ์‹œ๊ธ€์€ ๋ชจ๋“  CRUD๊ธฐ๋Šฅ์ด ๋‹ค ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์•„์ฃผ ํŽธํ•œ ๋งˆ์Œ์œผ๋กœ ViewSet์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

๋Œ€์‹  ์•ž์„œ ์„ ์–ธํ•œ๋Œ€๋กœ ๊ฐ๊ธฐ ๋‹ค๋ฅธ ์‹œ๋ฆฌ์–ผ๋ผ์ด์ €๋ฅผ ์ ์žฌ ์ ์†Œ์— ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด ์ฃผ๋ฉด ๋˜๊ฒ ์Šต๋‹ˆ๋‹ค. 

 

+ ๋˜ํ•œ ๊ฒŒ์‹œ๊ธ€์„ ์ƒ์„ฑํ•  ๋•Œ ์œ ์ €๊ฐ€ ์ž…๋ ฅํ•ด์ฃผ์ง€ ์•Š๋Š” ์ €์ž ์ •๋ณด๋ฅผ ๊ฐ™์ด ๋„ฃ์„ ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. 

+ ๊ฐ ์ƒํ™ฉ์— ๋”ฐ๋ผ ํ•„์š”ํ•œ ๊ถŒํ•œ์ด ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์šฐ๋ฆฌ๋Š” ์•ž์„œ ์ž‘์„ฑํ–ˆ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ permission.py ํŒŒ์ผ์„ posts์•ฑ ๋‚ด์— ์ž‘์„ฑํ•˜์—ฌ ์‚ฌ์šฉ

์ด๋ ‡๊ฒŒ ์ •์˜๋œ CustomReadOnly ๊ถŒํ•œ ํด๋ž˜์Šค๋Š” Django REST Framework์˜ ์ธ์ฆ๊ณผ ๊ถŒํ•œ ์‹œ์Šคํ…œ๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋ทฐ์˜ permission_classes ์†์„ฑ์— CustomReadOnly๋ฅผ ์ง€์ •ํ•จ์œผ๋กœ์จ ํ•ด๋‹น ๋ทฐ์—์„œ ์ •์˜ํ•œ ๊ถŒํ•œ ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ, ๊ธ€ ์กฐํšŒ(GET) ์š”์ฒญ์€ ๋ˆ„๊ตฌ๋‚˜ ํ—ˆ์šฉ๋˜๊ณ , ๊ธ€ ์ƒ์„ฑ(POST) ์š”์ฒญ์€ ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž๋งŒ ํ—ˆ์šฉ๋˜๋ฉฐ, ํŽธ์ง‘(PUT, PATCH, DELETE) ์š”์ฒญ์€ ํ•ด๋‹น ๊ธ€์˜ ์ž‘์„ฑ์ž๋งŒ ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค.

์œ„์˜ PostViewSet ํด๋ž˜์Šค๋Š” ModelViewSet์„ ์ƒ์†๋ฐ›์•˜๊ธฐ ๋•Œ๋ฌธ์— list, retrieve, create, update, partial_update, destroy ๋“ฑ์˜ ๊ธฐ๋ณธ์ ์ธ CRUD ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด Post ๋ชจ๋ธ์— ๋Œ€ํ•œ ์กฐํšŒ, ์ƒ์„ฑ, ์—…๋ฐ์ดํŠธ, ์‚ญ์ œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ CustomReadOnly ๊ถŒํ•œ ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด ์ฝ๊ธฐ ์ „์šฉ ์š”์ฒญ์— ๋Œ€ํ•œ ๊ถŒํ•œ ์ œ์–ด๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

 

 

6.3.5 URL

๋ทฐ์…‹์„ ์‚ฌ์šฉํ•˜๋‹ˆ ๋ผ์šฐํ„ฐ๋„ ํ•จ๊ป˜ ๋”ฐ๋ผ์˜ต๋‹ˆ๋‹ค. 

์•ž์„œ ๋ฐฐ์› ๋˜ ๋Œ€๋กœ ๋ผ์šฐํ„ฐ๋ฅผ ํ™œ์šฉํ•ด posts/urls.py ๋ฅผ ์„ค์ •ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. 

 

myboard/urls.py 

 

6.3.6 ์‹คํ–‰

๊ฒŒ์‹œ๊ธ€์ด ์ž˜ ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. 

 

6.3.7. ํ•„ํ„ฐ๋ง

ํ•„ํ„ฐ๋ง์€ ๊ฒŒ์‹œ๊ธ€๋“ค ์ „์ฒด๋ฅผ ๊ฐ€์ ธ์˜ค๋ ค ํ•  ๋•Œ ์กฐ๊ฑฐ๋Šฅใ„น ๊ฑธ์–ด ๊ฐ€์ ธ์˜ค๊ฒŒ๋” ํ•˜๋Š” ๊ธฐ๋Šฅ

pip install django-filter

 

6.3.8 ํŽ˜์ด์ง•

์ „์ฒด ์กฐํšŒ ํŽ˜์ด์ง€๋ฅผ ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€๋กœ ๋‚˜๋ˆ„๊ฑฐ๋‚˜ ํ•œ ๋ฒˆ์— ๋ชจ๋“  ๊ธ€์„ ๊ฐ€์ ธ์˜ค๊ธฐ ๋ถ€๋‹ด์Šค๋Ÿฌ์šธ ๊ฒฝ์šฐ ํ•œ ๋ฒˆ์˜ API ์š”์ฒญ์œผ๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ ์ˆ˜๋ฅผ ์ œํ•œํ•˜๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. 

'DEFAULT_PAGINATION_CLASS':
    'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE':
    3,

 

 

6.3.9 ์ข‹์•„์š”

๋งˆ์ง€๋ง‰ ๊ธฐ๋Šฅ์€ ๋Œ€๋ง์˜ ์ข‹์•„์š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

์ข‹์•„์š” ๊ธฐ๋Šฅ์€ ์˜ค์ง likes ํ•„๋“œ์—๋งŒ ์˜ํ–ฅ์„ ์ฃผ๊ณ  ๊ฐ„๋‹จํ•œ GET ์š”์ฒญ ํ•˜๋‚˜๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

@api_view(['GET'])
@permission_classes([IsAuthenticated])
def like_post(request, pk):
    post = get_object_or_404(Post, pk=pk)
    if request.user in post.likes.all():
        post.likes.remove(request.user)
    else:
        post.likes.add(request.user)

    return Response({'status': 'ok'})

 

 

 

6.4 ์•ฑ: ๋Œ“๊ธ€

 

6.4.3 ์‹œ๋ฆฌ์–ผ๋ผ์ด์ €
from rest_framework import serializers

from users.serializers import ProfileSerializer
from .models import Post, Comment


class CommentSerializer(serializers.ModelSerializer):
    profile = ProfileSerializer(read_only=True)

    class Meta:
        model = Comment
        fields = ("pk", "profile", "post", "text")


class CommentCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Comment
        fields = ("post", "text")


class PostSerializer(serializers.ModelSerializer):
    profile = ProfileSerializer(read_only=True)
    comments = CommentSerializer(many=True, read_only=True)

    class Meta:
        model = Post
        fields = ("pk", "profile", "title", "body", "image", "published_date",
                  "likes", "comments")


class PostCreateSerializer(serializers.ModelSerializer):
    # image = serializers.ImageField(use_url=True, required=False)

    class Meta:
        model = Post
        fields = ("title", "category", "body", "image")

 

6.4.4 ๋ทฐ

 

6.4.5 URL

์—๋Ÿฌ ์—†์ด ์‘๋‹ต์ด ์˜ต๋‹ˆ๋‹ค.

์ข‹์•„ ์š” ๊ธฐ๋Šฅ์ด ์ž˜ ์ž‘๋™ํ–ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด 1๋ฒˆ ๊ฒŒ์‹œ๊ธ€์„ ์กฐํšŒํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค. 

๊ฒŒ์‹œ๊ธ€์„ ํ™•์ธํ•ด๋ณด๋ฉด ๋น„์–ด์žˆ๋˜ likes์— 4๋ฒˆ ์œ ์ €๊ฐ€ ์ถ”๊ฐ€๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

 

๋‹ค์‹œ ์ข‹์•„์š” ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด ์ข‹์•„์š”๊ฐ€ ์ทจ์†Œ๋˜๋ฉด์„œ 4๋ฒˆ ์œ ์ €๊ฐ€ ์‚ญ์ œ๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

 

์•ฑ : ๋Œ“๊ธ€

๋Œ“๊ธ€ ์•ฑ์„ ๋งŒ๋“ค๊ณ  ๋Œ“๊ธ€ ๊ด€๋ จ ๊ธฐ๋Šฅ์„ ๊ฐœ๋ฐœํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. 

 

6.4.2 ๋Œ“๊ธ€ ๋ชจ๋ธ & ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜

์šฐ์„  ๋ชจ๋ธ๋ถ€ํ„ฐ ๋งŒ๋“ค๊ฒ ์Šต๋‹ˆ๋‹ค. 

๋Œ“๊ธ€๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ ๊ฒŒ์‹œ๊ธ€๊ณผ ์•„์ฃผ ๋ฐ€์ ‘ํ•œ ์—ฐ๊ด€์ด ์žˆ๋‹ค๋ณด๋‹ˆ ๊ตณ์ด ์•ฑ์„ ๋”ฐ๋กœ ๋งŒ๋“ค์ง€ ์•Š์•„๋„ ๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. 

class Comment(models.Model):
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    profile = models.ForeignKey(Profile, on_delete=models.CASCADE)
    post = models.ForeignKey(Post,
                             related_name='comments',
                             on_delete=models.CASCADE)
    text = models.TextField()

 

6.4.3 ์‹œ๋ฆฌ์–ผ๋ผ์ด์ €

 

 

 

 

6.4.6 ์‹คํ–‰

 

 

 

6.5 ๋ฐฐํฌํ•˜๊ธฐ

 

"์ด ํฌ์ŠคํŒ…์€ ์ฟ ํŒก ํŒŒํŠธ๋„ˆ์Šค ํ™œ๋™์˜ ์ผํ™˜์œผ๋กœ, ์ด์— ๋”ฐ๋ฅธ ์ผ์ •์•ก์˜ ์ˆ˜์ˆ˜๋ฃŒ๋ฅผ ์ œ๊ณต๋ฐ›์Šต๋‹ˆ๋‹ค."