ํ’€์Šคํƒ ์›น๐ŸŒ ๊ฐœ๋ฐœ์ž ์ง€๋ง์ƒ ๐Ÿง‘๐Ÿฝโ€๐Ÿ’ป
โž• ์ธ๊ณต์ง€๋Šฅ ๊ด€์‹ฌ ๐Ÿค–


Categories


Recent views

  • 1
  • 2
  • 3
  • 4
  • 5

Django ๊ธฐ๋ณธ

  1. django์˜ ๊ฐœ๋…
    • MVC(Model View Controller), MTV(Model Template View) ํŒจํ„ด
      • django ์ƒ์„ฑ๋ฒ•๊ณผ ๊ฐ€์ƒํ™˜๊ฒฝ์„ค์ •
        • django ์•ฑ ์ถ”๊ฐ€ ๋ฐฉ๋ฒ•
          • url๋กœ ์•ฑ์— ๋ณ€์ˆ˜ ๋„˜๊ฒจ์ฃผ๊ธฐ (variable routing)
          • DTL (django template language)
          • ERD ( Entity Relationship Diagram)
            • if ๋ฌธ์„ ์ด์šฉํ•œ restfullํ•œ ์›น์ฝ”๋”ฉ

            django ํ”„๋ ˆ์ž„์›Œํฌ

            django์˜ ๊ฐœ๋…

            django ํด๋” ์ฐธ์กฐ

            • ๋‹ค์†Œ ๋…์„ ์ 
            • ๊ด€์šฉ์ 
            • ์ •์ ์ธ ์›น์„ ๋™์ ์ธ ์›น์œผ๋กœ ๋ฐ”๊ฟˆ
            • ๊ธฐ๋ณธ์ ์ธ ๊ตฌ์กฐ, ํ•„์š”ํ•œ ์ฝ”๋“œ๋ฅผ ์ œ๊ณตํ•ด์คŒ
            • ์œ ํŠœ๋ธŒ, ๋‚˜์‚ฌ, ์ธ์Šคํƒ€๊ทธ๋žจ ๋“ฑ

            MVC(Model View Controller), MTV(Model Template View) ํŒจํ„ด

            • MVC(model view controller) ํŒจํ„ด : ๋ชจ๋“  ์›น ์„œ๋น„์Šค๋ผ๋ฉด ๋ชจ๋‘ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋””์ž์ธ ํŒจํ„ด
            • MTV(model template view) : ํŒŒ์ด์ฌ์ด ๋ฐ”๊พผ ์ด๋ฆ„, ํž™์Šคํ„ฐ ์‰‘ ใ…‹
              • ๋ชจ๋ธ: ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌ, ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ๊ทธ ์ž์ฒด
              • ํ…œํ”Œ๋ฆฟ : ์‚ฌ์šฉ์ž๊ฐ€ ๋ณด๋Š” ํ™”๋ฉด,
              • ๋ทฐ : ์ค‘๊ฐ„ ๊ด€๋ฆฌ์ž ์š”์ฒญ์„ ๋ฐ›์•„์„œ ๋ชจ๋ธ์—๊ฒŒ ๋ฐ์ดํ„ฐ ์ฐพ์œผ๋ผ๊ณ  ๋ช…๋ นํ•˜๊ณ  ๋ชจ๋ธ์—๊ฒŒ์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์€๋’ค ํ…œํ”Œ๋ฆฟ์œผ๋กœ ๋ณด๋ƒ„

            ## django_intro ํด๋” (ํ”„๋กœ์ ํŠธ ํด๋”) ๋‚ด๋ถ€ ํŒŒ์ผ
            __init__.py : ํŒจํ‚ค์ง€๋กœ ์ธ์‹ํ•˜๊ฒŒ ํ•ด์คŒ
            wsgi.py : ์›น์„œ๋ฒ„ ๊ฒŒ์ดํŠธ์›จ์ด ์ธํ„ฐํŽ˜์ด์Šค
            settings.py : ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์„ค์ •์— ๊ด€๋ จ๋œ ๊ฒƒ
            urls.py : flask์˜ app.route ์—ญํ• 

            django-admin startapp pages : pages ํด๋”๋ฅผ ๋งŒ๋“ฌ ๋‚ด๋ถ€ ๊ตฌ์กฐ๋Š” ์ƒ๋‹นํžˆ ์œ ์‚ฌํ•จ
            admin.py : ๊ด€๋ฆฌํ•˜๋Š” ๊ณต๊ฐ„
            apps.py : ์—ก์—๋Œ€ํ•œ ์„ค์ •
            models.py : ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๊ด€๋ จ๋œ ๊ฒƒ Mใ…‡TV ๊ด€๋ จ
            testsp.py : ํ…Œ์ŠคํŒ…์šฉ
            views.py : ์ค‘๊ฐ„๊ด€๋ฆฌ์ž MTV ๊ด€๋ จ
            ์žฅ๊ณ ๋Š” ํ”„๋กœ์ ํŠธ ๋‚ด๋ถ€์— ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์•ฑ์„ ๋งŒ๋“œ๋Š” ํ˜•์‹

            settings.py์˜ Installed_Apps ๋ž€์— pages๋ฅผ ๋“ฑ๋กํ•˜๋ฉด ์•ฑ์„ ๋“ฑ๋กํ•˜๋Š” ํ–‰์œ„์ž„ (์ปค์Šคํ…€์€ ๋งจ์œ„์— ๋†“์€ ๊ฒƒ์„ ๊ถŒ์žฅ, ์ด๋ฆ„์ด ๊ฐ™์œผ๋ฉด ๋งจ์œ„ ๋ฆฌ์ŠคํŠธ์— ์žˆ๋Š” ๊ฒƒ์„ ๊ฐ€์ ธ์˜ด)

            USE_I18N = ์œ„์—์žˆ๋Š” Lanugate_code ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ธ๊ฐ€?

            django ์ƒ์„ฑ๋ฒ•๊ณผ ๊ฐ€์ƒํ™˜๊ฒฝ์„ค์ •

            1. mkdir 13workshop
            2. cd 13workshop
            3. python -m venv venv
            4. source venv/Scripts/activate
            5. pip install django
            6. django-admin startproject classroom . (. ์•ˆ์ฐ์œผ๋ฉด ๊ฐ™์€ ์ด๋ฆ„์˜ ํด๋”๋ฅผ ์ถ”๊ฐ€ ํ›„ ์ƒ์„ฑ)
            7. python manage.py runserver
            ์„ ํƒ:
            .gitignore ํŒŒ์ผ ์•ˆ์— ์„ค์ •
            django-admin startapp pages๋กœ pages ์•ฑ ์ƒ์„ฑ (ํ”„๋กœ์ ํŠธ ํด๋” ๋ฐ”๊นฅ์—์„œ?)
            python manage.py startapp your_app_name (์•ฑ ์ƒ์„ฑ 2)
            
            

            ๊ฐ€์ƒ ํ™˜๊ฒฝ ์„ค์ • : ์›น ๋””๋ฒจ๋กœํ•‘์— ํ•„์š”ํ•œ ๋ชจ๋“ˆ๋งŒ python์— ์Œ“๋Š”๊ฒƒ (์˜ˆ๋ฅผ๋“ค์–ด jupyter ๊ฐ™์€๊ฑฐ ํ•„์š” ์—†์Œ)

            python -m venv ํด๋”์ด๋ฆ„ : ์ฒ˜์Œ venv๋Š” ๋ฒ„์ „ ํ™˜๊ฒฝ(version environment)์˜ ์ค€๋ง ํ•ด๋‹น ๋””๋ ‰ํ† ๋ฆฌ์— ํด๋”์ด๋ฆ„์ด ๋˜์–ด์žˆ๋Š” ๊ฐ€์ƒํ™˜๊ฒฝ์„ ๋งŒ๋“ค์–ด์คŒ

            ๋””๋ ‰ํ† ๋ฆฌ ์•ˆ์—์„œ source ํด๋”์ด๋ฆ„/Scripts/activate ํ•˜๋ฉด (๋˜๋Š” ๊ฑฐ๊ธฐ์„œ ๊ทธ ํŒŒ์ผ์„ ํด๋ฆญ) (venv)๋ผ๋Š” ํ‚ค์›Œ๋“œ๊ฐ€ ํ„ฐ๋ฏธ๋„์— ๋œธ
            ์•ˆ์—์„œ ์“ธ๋ชจ์—†๋Š” ํŒจํ‚ค์ง€๊ฐ€ ์—†์–ด์ง
            deactivate ํ•˜๋ฉด ๋‹ค์‹œ ์‚ฌ๋ผ์ง

            ๋˜๋Š” vscode์—์„œ f1์œผ๋กœ select interpreter์„ ๊ณ ๋ฅธํ›„, venv ํ™˜๊ฒฝ์˜ ํŒŒ์ด์ฌ์„ ๊ณ ๋ฅด๋ฉด ํ„ฐ๋ฏธ๋„์—์„œ (venv)๊ฐ€ ํ™œ์„ฑํ™” ๋˜์–ด์žˆ์Œ
            django-admin startproject django_intro . ๋กœ ํ˜„์žฌ ํด๋”์— ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ
            python manage.py runserver ๋กœ ์„œ๋ฒ„ ๋Œ๋ฆฌ๊ธฐ

            django-admin startapp pages๋กœ pages ์•ฑ ์ƒ์„ฑ
            python manage.py startapp your_app_name (์•ฑ ์ƒ์„ฑ 2)

            django ์•ฑ ์ถ”๊ฐ€ ๋ฐฉ๋ฒ•

             ๋Œ€๋žต์ ์ธ ํ๋ฆ„ : 
            1. urls.py์—์„œ urlpatterns ๋ฆฌ์ŠคํŠธ์— path("url์ด๋ฆ„/", views.url์ด๋ฆ„), ์„ ๋“ฑ๋ก , 2๋ฒˆ์งธ views.url์ด๋ฆ„์€ views.py์— ์˜ฌ๋ผ๊ฐ€๋Š” ํ•จ์ˆ˜ ์ด๋ฆ„์ž„, 1๋ฒˆ์งธ url ์ด๋ฆ„ ๋’ค์— / ํ•„์ˆ˜ (django๊ฐ€ ์ž๋™์œผ๋กœ ๋งˆ์ง€๋ง‰์— /๋ฅผ ๋ถ™์ด๋ฏ€๋กœ ์—†์œผ๋ฉด ์ ˆ๋Œ€ ์ ‘๊ทผํ• ์ˆ˜ ์—†์Œ)
            2. views.py์— url์ด๋ฆ„๊ณผ ๊ฐ™์€ ํ•จ์ˆ˜(๋˜๋Š” 1๋‹จ๊ณ„์— ์ •์˜ํ•œ 2๋ฒˆ์งธ ์ธ์ž)๋ฅผ ์ •์˜ (request๋Š” ๋ฌด์กฐ๊ฑด ์ฒ˜์Œ ์ธ์ž์— ํฌํ•จ), 
            3. return์œผ๋กœ render(request, 'html์ด๋ฆ„', context), context๋Š” ๋„˜๊ฒจ์ค„ ์ธ์ž๋“ค์˜ dictionary, 
            4. pages ํด๋”์˜ templatesํด๋”๋‚ด์— url์ด๋ฆ„.html์— ํŒŒ์ผ ๋งŒ๋“ค๊ณ  html ์ฝ”๋“œ ๊ตฌ์„ฑ, 
            5. ์ธํ„ฐ๋„ท์— ํ•ด๋‹น url๋กœ ๊ฐ€๋ณด๋ฉด ์™„์„ฑ
            
            

            url๋กœ ์•ฑ์— ๋ณ€์ˆ˜ ๋„˜๊ฒจ์ฃผ๊ธฐ (variable routing)

            https://์„œ๋ฒ„์ฃผ์†Œ/greeting/์œค์ค€์„/
            
            

            path(โ€˜greeting//', views.greeting) ์ด๋Ÿฐ์‹์œผ๋กœ name ๋ฌธ์ž์—ด์„ ๋„˜๊ฒจ์ค„ ์ˆ˜ ์žˆ์Œ, ์ด๋Ÿฌ๋ฉด views.py์— ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค๋•Œ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ name ์„ ๋ฌธ์ž์—ด๋กœ ๋„˜๊ฒจ์ฃผ๋ฉด ์›น ํŽ˜์ด์ง€ url์„ ํ†ตํ•ด ํ•ด๋‹น ๋ณ€์ˆ˜๋ฅผ ๋„˜๊ฒจ์ฃผ๋ฉด ๋ฐ›์„ ์ˆ˜ ์žˆ์Œ str์ด ์•„๋‹ˆ๋ผ int๋ฉด ํƒ€์ž…์ด ์ •์ˆ˜ํ˜•์œผ๋กœ ๋ฐ”๋€œ

            path(โ€˜mul//', views.mul) ์ด๋Ÿฐ์‹์œผ๋กœ ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ธ์ˆ˜๋ฅผ ๋„˜๊ฒจ์ค„ ์ˆ˜๋„ ์žˆ์œผ๋ฉฐ, ํ•ด๋‹น ๋งค๊ฐœ๋ณ€์ˆ˜๋“ค์„ ์—ฐ์‚ฐํ•˜๋ ค๋ฉด views.py์˜ ํ•จ์ˆ˜ ๋‚ด์—์„œ ํ•ด์•ผํ•œ๋‹ค. ์ด๋Ÿฐ์‹์œผ๋กœ ๋™์ ์ธ ์›น, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ID์— ๋”ฐ๋ฅธ ์•„์ด๋””์— ๋”ฐ๋ฅธ ์›นํŽ˜์ด์ง€ ์ž๋™์ƒ์„ฑ๋“ฑ์— ์“ด๋‹ค.

            url namespacing

            • url์„ html ํŒŒ์ผ์— ํ•˜์ดํผ๋งํฌ๋กœ ๋„˜๊ฒจ์ค„ ๋•Œ, DTL์„ ์ด์šฉํ•˜์—ฌ ๋ณ€์ˆ˜ํ™”ํ•ด์„œ ๋„˜๊ฒจ์ค„ ์ˆ˜ ์žˆ๋‹ค.

              namspacing ์˜ˆ์‹œ์™€ ๊ธฐ์กด์˜ url ํ• ๋‹น๋ฒ•(๋ฐ‘)
              ```html
              <a href="{% url 'todos:index' %}">์ „์ฒด๊ธ€๋ณด๊ธฐ</a>
              <a href="/todos/new/">์ƒˆ๋กœ ๊ฒŒ์‹œ๊ธ€ ์ž‘์„ฑํ•˜๊ธฐ</a>>

            - ๊ธฐ์กด์˜ url ํ• ๋‹น ๋ฒ•์—์„œ๋Š” /๋ฅผ ๋งจ ์•ž์— ์ถ”๊ฐ€ํ•˜๋ฉด root ์ฃผ์†Œ ์•ž์— ํ•ด๋‹น ์ฃผ์†Œ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค
            - /๊ฐ€ ์—†๋‹ค๋ฉด ํ˜„์žฌ ์ฃผ์†Œ์— ์ถ”๊ฐ€๋กœ /๋ฅผ ๋ถ™์—ฌ์„œ ์ถ”๊ฐ€ํ•œ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค
            > ์œ„ ๊ธฐ์กด url ํ• ๋‹น๋ฒ•์˜ /๊ฐ€ ์—†๋Š” ์˜ˆ์‹œ
            ```html
            <a href="new/">์ƒˆ๋กœ ๊ฒŒ์‹œ๊ธ€ ์ž‘์„ฑํ•˜๊ธฐ</a>
            
            
            • ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๊ธฐ์กด์˜ ๊ฒฝ๋กœ์— ์ถ”๊ฐ€๋˜๋Š” ํ˜•์‹, ์ด๊ฒƒ์„ ์‹ ๊ฒฝ ์“ฐ๊ธฐ ํž˜๋“œ๋ฏ€๋กœ ๋ณ€์ˆ˜ํ™” (namespacing)ํ•œ๋‹ค.

            • ๋„ค์ž„ ์ŠคํŽ˜์ด์‹ฑ์„ ์œ„ํ•ด ๋จผ์ € ํ•ด๋‹น ์•ฑ์˜ ์•ฑ ๋„ค์ž„์„ ์„ ์–ธํ•œ๋‹ค

              ์•ฑ๋„ค์ž„ ์„ ์–ธ ์˜ˆ์‹œ(urls.py)
              ```python
              from django.urls import path
              from . import views

            app_name = 'todos' # ์ผ๋ฐ˜์ ์œผ๋กœ ์•ฑ ์ด๋ฆ„๊ณผ ๊ฐ™์€ ์ด๋ฆ„์„ ๋„ฃ์Œ

            urlpatterns = [
            path('', views.index, name="index"),
            path('new/', views.new, name="new"),# ํผ ๋ณด์—ฌ์ฃผ๊ธฐ
            path('create/', views.create, name="create"), # ๋ฐ›์€ ํผ์˜ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๊ธฐ
            path('<int:id>/delete/', views.delete, name="delete"), # ๋ณ€์ˆ˜๋กœ ์ด์šฉํ•˜๋ฉด ์—ฌ๊ธฐ์„œ๋งŒ / ์‹ ๊ฒฝ์“ฐ๋ฉด ๋จ
            # ๋์— /๋ฅผ ๊ผญ ๋ถ™์—ฌ์ฃผ์ž.
            ]

            - ์ด๋ฅผ ํ•ด์ฃผ๋ฉด ๋‹ค๋ฅธ ์•ฑ์—์„œ url ๋ณ€์ˆ˜๊ฐ€ ๊ฒน์ณ๋„ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ์ง€ ์•Š๋Š”๋‹ค.
            - ๋˜ํ•œ ๋ณ€์ˆ˜ํ™”ํ•  path ํ•จ์ˆ˜์— name์— ๋ณ€์ˆ˜๋ช…์„ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค.
            > variable routing ์ด ์ ์šฉ๋œ namespacing ์˜ˆ์‹œ
            ```html
            <a href="{% url 'todos:delete' todo.id %}">์‚ญ์ œ</a>
            
            
            • ํ™‘๋”ฐ์˜ดํ‘œ ์Œ๋”ฐ์˜ดํ‘œ๋ฅผ ๋ฒˆ๊ฐˆ์•„๊ฐ€์„œ ์“ฐ์ง€ ์•Š์•„๋„ ๋˜๋‚˜, ๊ทธ๋Ÿฌ๋ฉด python ๋ฌธ๋ฒ•์œผ๋กœ ์ธํ•ด ๋ณด๊ธฐ ํ‰ํ•ด์ง„๋‹ค.(๊ถŒ์žฅ)
            • โ€{% url โ€˜์•ฑ์ด๋ฆ„:url๋ณ€์ˆ˜๋ช…โ€™ ๋งค๊ฐœ๋ณ€์ˆ˜1๊ฐœ, ๋งค๊ฐœ๋ณ€์ˆ˜ 2๊ฐœ..%}โ€๋ฅผ ํ•˜์ดํผ๋งํฌ๋กœ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค.
            • variable routing์ผ ๊ฒฝ์šฐ url ๋ณ€์ˆ˜ ๋„ฃ๊ธฐ ์•Œ์•„๋ณด๊ธฐ (todos์˜ index.html)

              DTL (django template language)

              : jinja๋ž‘ ๋ฌธ๋ฒ•์ด ์ƒ๋‹นํžˆ ๋น„์Šทํ•จ

            for๋ฌธ ์˜ˆ์‹œ
            ```html
            {% for menu in menus %}
            <li>{{forloop.counter}} : {{menu}}</li>
            {% empty %}
            <p>๋ฆฌ์ŠคํŠธ๊ฐ€ ๋น„์–ด์žˆ์Šต๋‹ˆ๋‹ค.</p>
            {% endfor %}
            <!โ€“forloop.counter:for๋‚ด๋ถ€์—์„œ๋งŒ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•จ ๋ฐ˜๋ณต ์ˆซ์ž ํ‘œ์‹œํ•ด์คŒ enumerate ์ฒ˜๋Ÿผ ์“ธ์ˆ˜ ์žˆ์Œ, ๋ฌธ์žฅ์€ {% ์‚ฌ์ด์— ์ŠคํŽ˜์ด์Šค๋ฐ”๋กœ ๋„์–ด์„œ %}, ๋ณ€์ˆ˜๋Š” {%์•ˆ๋„์›€%}
            {% empty %}๋Š” ๋งŒ์•ฝ ํ•ด๋‹น ๋ฆฌ์ŠคํŠธ๊ฐ€ ๋น„์–ด์žˆ๋‹ค๋ฉด ์•„๋ž˜ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋จโ€“>

            - ๋งŒ์•ฝ ๋ฆฌ์ŠคํŠธ์˜ ์›์†Œ์— ์ธ๋ฑ์Šค๋กœ ์ ‘๊ทผํ•˜๊ณ  ์‹ถ์œผ๋ฉด {{๋ณ€์ˆ˜.์ธ๋ฑ์Šค}}๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.
            - ex) student.0
            - forloop + first๋‚˜ last๋ฅผ ์น˜๋ฉด ์ฒ˜์Œ ์›์†Œ๋‚˜ ๋งˆ์ง€๋ง‰ ์›์†Œ์ผ๋•Œ true๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
            
            > ์กฐ๊ฑด๋ฌธ ์˜ˆ์‹œ	
            ```html
              <h3>์กฐ๊ฑด๋ฌธ</h3>
              {% if 'ํ•œ์‹' in menus %}
              <p>์—ญ์‹œ ํ•œ๊ตญ์ด๋ผ๋ฉด ํ•œ์‹์ด์ง€</p>
              {% endif %}
            
            

            ์กฐ๊ฑด๋ฌธ๊ณผ else๋ฌธ, elif๋ฌธ, for๋ฌธ๊ณผ์˜ ์ค‘์ฒฉ ์˜ˆ์‹œ
            ```html
            {% for menu in menus %}

            <p>{{forloop.counter}}๋ฒˆ์งธ ๋ฐ˜๋ณต๋ฌธ ๋„๋Š”์ค‘โ€ฆ</p>
            {% if 'ํ•œ์‹' == menu %}
            <p>์—ญ์‹œ ํ•œ๊ตญ์ธ์€ ํ•œ์‹์ด์ง€</p>
            {% elif '์ผ์‹' == menu %}
            <p>์ด๊ฒƒ๋„ ๋ถˆ๋งค ์šด๋™ ํ•ด์•ผํ•˜๋‚˜?</p>
            {% else %}
            <p>{{menu}}</p>
            {% endif %}
            {% endfor %}

            - DTL ๋‚ด๋ถ€์—์„œ๋Š” ๊ด„ํ˜ธ()๋ฅผ ์“ธ ์ˆ˜ ์—†๋‹ค.
            
            - ์™ ๋งŒํ•˜๋ฉด ํŒ๋‹จ์€ views์—์„œ ๋จผ์ € ํ•˜์ž
            
              
            
            1) ํ•จ์ˆ˜ ์•ˆ์—์„œ ๋‹ค๋ฅธ ํŽ˜์ด์ง€์˜ ํผ์—์„œ ์ž…๋ ฅํ•œ ๋ฐ์ดํ„ฐ ๋ฐ›๊ธฐ (๋”•์…”๋„ˆ๋ฆฌ ํ˜•ํƒœ)
            
            

            request.GET.get('name')

            - queryDict๋ผ๋Š” ์ƒˆ๋กœ์šด ํ˜•์‹์ด๋ฏ€๋กœ GET์„ ํ†ตํ•˜์—ฌ ํ‰๋ฒ”ํ•œ dict๋กœ ๋งŒ๋“  ๋’ค, get() ๋ฉ”์„œ๋“œ๋กœ ๋ฐ›๋Š”๊ฒƒ
            
            - url์—๋Š” _(์–ธ๋”๋ฐ”)๋ฅผ ์“ฐ๋ฉด ํ•˜์ดํผ๋งํฌ ์ ์šฉ์‹œ ํŒŒ๋ž€ ์•„๋žซ์ค„ ๋•Œ๋ฌธ์— ์•ˆ๋ณด์ด๋ฏ€๋กœ ์™ ๋งŒํ•˜๋ฉด -(ํ•˜์ดํ”ˆ)์„ ์“ฐ์ž
            
            

            <form action="/post-pong/" method="POST">
            {% csrf_toekn %}
            <input> ์–ด์ฉŒ๊ตฌ ์ €์ฉŒ๊ตฌ
            </form>

            - method ์•ˆ๋„ฃ์œผ๋ฉด ๊ธฐ๋ณธ GET ๋ฐฉ์‹, ๋Œ€์†Œ๋ฌธ์ž ๊ตฌ๋ถ„ ์•ˆํ•จ
            - POST๋ฅผ ๋„ฃ์œผ๋ฉด ์ข€๋” ์•ˆ์ „ํ•˜๊ณ  CSRF์— ๋Œ€๋น„ํ•˜๋ฏ€๋กœ csrf_token ํ•„์š”,
            - ์ด๋•Œ๋Š” requset.POST.get('name') ๋ฐฉ์‹์œผ๋กœ ๋ฐ›์•„์™€์•ผํ•จ
            - {% csrf_token %}์„ ํผ์•ˆ์— ๋„ฃ์–ด์„œ ํ† ํฐ ๋ถ€์—ฌ ํ•˜๋ฉด ์•”ํ˜ธํ™”? ๊ฐ™์€๊ฒŒ ๋จ
            	- csrf_token = ๋žœ๋คํ•œ ๋ฌธ์ž์—ด์„ ์ƒ์„ฑํ•ด์คŒ type="hidden"์ด ๋˜์–ด์„œ ๋žœ๋ค ๋ฌธ์ž์—ด์„ ์ธ์ฆํ•ด์คŒ
            
            - ์ด๋Ÿฌ๋ฉด URL์— ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋“ค์ด ๋ณด์ด์ง€ ์•Š์Œ, ๊ฐœ๋ฐœ์ž๋„๊ตฌ ํ—ค๋”์Šค์—์„œ์˜ formdata์—์„œ  ํ™•์ธ ๊ฐ€๋Šฅ
            - GET์€ ๋ณด๋‚ด์ฃผ์„ธ์š”, POST๋Š” ์ฒ˜๋ฆฌํ•ด์ฃผ์„ธ์š” ๋ผ๋Š” ์˜๋ฏธ
            - GET : ์„œ๋ฒ„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€ํ™”์‹œํ‚ค์ง€ ์•Š์Œ
            - POST : ์„œ๋ฒ„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€ํ™”์‹œํ‚ด (๋Œ€๋ถ€๋ถ„์˜ ๋ฐ์ดํ„ฐ ์ด์šฉ์— ์ ํ•ฉ)
            CSRF : ์‚ฌ์ดํŠธ๊ฐ„ ์š”์ฒญ ์œ„์กฐ ๊ณต๊ฒฉ,  
            
            ##  static ํ‚ค์›Œ๋“œ๋กœ ํŒŒ์ผ๊ฐ€์ ธ์˜ค๊ธฐ, static ํ•˜๋‹ค : ๋ณ€ํ™”๊ฐ€ ์—†๋‹ค
            
            > base.html block ์„ค์ •
            ```html
            <!DOCTYPE html>
            <html lang="en">
            <head>
              <meta charset="UTF-8">
              <meta name="viewport" content="width=device-width, initial-scale=1.0">
              <meta http-equiv="X-UA-Compatible" content="ie=edge">
              <title>Document</title>
            </head>
            <body>
            <h1>Base is everywhere!</h1>
            {% block body1 %}
            {% endblock %}  
            {% block body2 %}
            {% endblock %}  
            </body>
            </html>
            
            
            • ํŒŒ๋น„์ฝ˜(favicon) : ์›นํŽ˜์ด์ง€ ์ด๋ฆ„ ์˜†์— ์žˆ๋Š” ์ž‘์€ ์•„์ด์ฝ˜

              ํŒŒ๋น„์ฝ˜ ์ถ”๊ฐ€ ๋ฐฉ๋ฒ•
              ```html
              ์•ฑ ๋‚ด๋ถ€์— static ํด๋” ์ƒ์„ฑ, ๊ทธ ๋‚ด๋ถ€์— ํŒŒ๋น„์ฝ˜์œผ๋กœ ์“ธ ์ด๋ฏธ์ง€ ํŒŒ์ผ ์ถ”๊ฐ€
              html ํŒŒ์ผ ๋งจ ์œ„์— ๋งจ ์œ„์ค„์—{% load static %} ์ถ”๊ฐ€
              html header์— <link rel="icon" href="{% static 'staticํด๋” ๋‚ด์˜ ํŒŒ์ผ ์ด๋ฆ„.ํŒŒ์ผํ™•์žฅ์ž' %}"> ์ถ”๊ฐ€(ico, png ํ™•์žฅ์ž ์ง€์›)

            > static ํ‚ค์›Œ๋“œ์˜ ์‚ฌ์šฉ๊ณผ block ์‚ฌ์šฉ
            ```html
            {% extends 'base.html' %} # base.html์—์„œ block์„ ๊ฐ€์ ธ์˜จ๋‹ค๋Š” ์˜๋ฏธ ํ•œ ํŒŒ์ผ์— 1๊ฐœ๋งŒ ํ—ˆ์šฉ
            {% load static %} 
            <!--ํด๋” ๊ฒฝ๋กœ๋Š” ์•ฑ ๋‚ด์˜ staticํด๋”์˜ cssํด๋” ๋‚ด๋ถ€-->
            {% block body1 %} # body1 block ๊ฐ€์ ธ์˜ค๊ธฐ
            <link rel="stylesheet" href="{% static 'css/style.css' %}">
            <h1>๋ณธ์˜ค๋ณธ์˜ค</h1>
            <img src="{% static 'image/feelthethunder.jpeg' %}" alt="">
            {% endblock %} # body1 block ๋‹ซ๊ธฐ
            {% block body2 %}# body2 block ๊ฐ€์ ธ์˜ค๊ธฐ
            {% endblock %}# base.html์— 2๊ฐœ์ด์ƒ ์ •์˜ํ–‡์„ ๊ฒฝ์šฐ
            
            
            • ์žฅ๊ณ  ๋ฌธ๋ฒ•์—์„œ static์€ ๋ณ€ํ•˜์ง€ ์•Š์„ ์ •๋ณด์— ๋ถ™์—ฌ์„œ ๊ฐ€์ ธ์˜ค๋Š”๋ฐ ์“ด๋‹ค.
            • ๋Œ€๋ถ€๋ถ„ ์„œ๋ฒ„๋ฅผ ๊ป๋‹ค ์ผœ์•ผ์ง€ ๋ณ€ํ™”๊ฐ€ ์ ์šฉ๋จ, ์˜ˆ์™ธ๋„ ์žˆ์Œ
            • load static์„ extends ๋ฐ‘์— ์จ์„œ ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ• ์ˆ˜ ์žˆ๊ฒŒ ๊ฐ€์ ธ์™€์•ผํ•œ๋‹ค.
            • ๋ณดํ†ต ๊ด€๋ก€์ƒ ํด๋” ์ด๋ฆ„์€ static์œผ๋กœ ํ•œ๋‹ค.

            3) ๋งŒ์•ฝ ๋‹ค๋ฅธ ์•ฑ์—๋„ ๊ฐ™์€ URL์˜ path๊ฐ€ ์žˆ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•  ๊ฒƒ์ธ๊ฐ€?

            master urls.py, ํ”„๋กœ์ ํŠธ ํด๋”์— ์žˆ๋Š” urls.py
            ```
            from django.contrib import admin
            from django.urls import path, include # django.urls ํŒจํ‚ค์ง€์— include ๊บผ๋‚ด์˜ด
            from pages import views

            path('pages/', include('pages.urls')), # pages ํด๋”์˜ ์„œ๋ธŒ urls.py์˜ url๋“ค์„ ๊ฐ€์ ธ์˜จ๋‹ค, include๋Š” ํ•ด๋‹น ํด๋”์˜ ํ•ด๋‹น ํŒŒ์ผ์„ ๊ฐ€์ ธ์˜ค๋Š” ํ•จ์ˆ˜
            path('utilities/', include('utilities.urls')), # utilities ํด๋”์˜ ์„œ๋ธŒ urls.py์˜ url๋“ค์„ ๊ฐ€์ ธ์˜จ๋‹ค

            > sub urls.py, pages ํด๋”(์•ฑ)์•ˆ์— ์žˆ๋Š” urls.py
            

            from django.urls import path
            from . import views # . ํ˜„์žฌ ํด๋”

            urlpatterns = [
            path('ping/', views.ping),
            path('pong/', views.pong),
            path('post-ping/', views.post_ping),
            path('post-pong/', views.post_pong),
            path('static-example/', views.static_example),
            ]

            - ๋งŒ์•ฝ pages์˜ ping url์— ์ ‘๊ทผํ•˜๊ณ  ์‹ถ์œผ๋ฉด https://์„œ๋ฒ„ ์ฃผ์†Œ/pages/ping/ ์œผ๋กœ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๋‹ค.
            
            - ๋งˆ์Šคํ„ฐ urls.py๊ฐ€ pages์˜ urls.py๋กœ ๊ถŒํ•œ๊ณผ ์š”์ฒญ์„ ๋„˜๊ธฐ๋Š” ํ˜•์‹
            
            ### SQL ORM
            #### DB
            - ๋ฐ์ดํ„ฐ๋“ค์˜ ๋ชจ์ž„
            - ์—ด, ์นผ๋Ÿผ, ๊ฐ ์—ด์—๋Š” ๊ณ ์œ ํ•œ ๋ฐ์ดํ„ฐ ํ˜•์‹์ด ์ง€์ •๋จ, ๋ฐ์ดํ„ฐ์˜ ์†์„ฑ
            - ํ–‰, ๋ ˆ์ฝ”๋“œ, 1๊ฐœ์˜ ๋ฐ์ดํ„ฐ
            - ์Šคํ‚ค๋งˆ, ํ‹€ ๊ฐ ์—ด์˜ ์š”์†Œ, ์ฆ‰  ๋“ค์–ด๊ฐˆ ๋ฐ์ดํ„ฐ์˜ ๋‚ด์šฉ์„ ์ •์˜ํ•จ
            #### ORM(Object-Relational Mapping)
            - SQL์ด ๋ชฐ๋ผ๋„ ํŒŒ์ด์ฌ ๋ฌธ๋ฒ•์œผ๋กœ ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์–ธ์–ด, ํŒŒ์ด์ฌ ์–ธ์–ด(์ดˆ์•ˆ, ์ฒญ์‚ฌ์ง„)์„ SQL ๋ฌธ์œผ๋กœ ํ•ด์„ํ•ด์คŒ, ์ค‘๊ฐ„ ๋ฒˆ์—ญ์ž
            
            ### CRUD
            
            - C: CREATE, ๋ฐ์ดํ„ฐ ์ƒ์„ฑ
            - R: READ, ๋ฐ์ดํ„ฐ ์ฝ๊ธฐ
            - U: UPDATE, ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ
            - D: DELETE, ๋ฐ์ดํ„ฐ ์ง€์šฐ๊ธฐ
            - ๋ฐ์ดํ„ฐ๋กœ ํ•  ์ˆ˜ ์žˆ๋Š” 4๊ฐ€์ง€
            
            #### ORM ์‚ฌ์šฉ๋ฒ•๊ณผ GIT BASH ๋ช…๋ น์–ด
            django-admin startapp posts : ์•ฑ ์ƒ์„ฑ
            
            > Student ๋ชจ๋ธ ์ƒ์„ฑ ์˜ˆ์‹œ (์•ฑ ๋‚ด๋ถ€์˜ models.py)
            ```python
            from django.db import models
            
            # Create your models here.
            {: #create-your-models-here}
            
            class Student(models.Model):
            # ๊ฐ๊ฐ colum ์ •์˜
            {: #๊ฐ๊ฐ-colum-์ •์˜}
                name = models.CharField(max_length=64)
                email = models.CharField(max_length=128) # ํ• ๋‹นํ•  ๋ฉ”๋ชจ๋ฆฌ(max_length) ์„ค์ •
                birthday = models.DateField()
                age = models.IntegerField()
            
                def __str__(self): # str ์˜ค๋ฒ„๋กœ๋”ฉํ•˜๋ฉด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ณด์—ฌ์คŒ
                    return f'์ด ํ•™์ƒ์˜ ์ด๋ฆ„์€ {self.name}'
            
            
            
            • model์„ ๋ฐ”๊พธ๋ฉด ๋‹ค์‹œ migrate๋ฅผ ํ•ด์ค˜์•ผ ์—…๋ฐ์ดํŠธ ๋˜๋ฉฐ ์™ ๋งŒํ•˜๋ฉด ๋ฐ”๊ฟ”์ฃผ์ง€๋ง์ž (๊ธฐ์กด์— ์ด๋ฏธ ์ถ”๊ฐ€๋œ ๋ฐ์ดํ„ฐ๋“ค์ด ๋ง์ฝ์„ ๋ถ€๋ฆฐ๋‹ค. ๋ณดํ†ต ๋‹ค ๋‚ ๋ฆฌ๊ณ  ๋‹ค์‹œ ๋งŒ๋“ฆ ๋จผ์ € ๋ชจ๋ธ๋ง ํ•˜์ž!)

            python manage.py makemigrations : ๋ชจ๋ธ์˜ 0001_initial.py ์ƒ์„ฑ (๋ฒˆ์—ญ๊ธฐ๋กœ ๋ฒˆ์—ญ ๋ณด๋‚ด๊ธฐ) (์ผ์ข…์˜ ๋ฐ์ดํ„ฐ ํ‘œ์˜ ํ—ค๋” ๋งŒ๋“ค๊ธฐ)

            Migrations for 'posts':
              posts\migrations\0001_initial.py
                - Create model Post
             # ์ด๋ ‡๊ฒŒ ๋œธ
            `
            

            python manage.py migrate: ํŒŒ์ด์ฌ ์ฝ”๋“œ๋ฅผ SQL ์–ธ์–ด๋กœ ํ•ด์„ํ•จ (๋ฒˆ์—ญ๋ณธ DB๋กœ ๋ณด๋‚ด ๋ช…๋ นํ•˜๊ธฐ) (์ผ์ข…์˜ ๋ฐ์ดํ„ฐ ์—‘์…€ ํ‘œ ๋งŒ๋“ค์–ด ๋†“๊ธฐ ๊ณต๊ฐ„๋งŒ๋“ค๊ธฐ)
            python manage.py shell (์ž‘์€ IDE? exit()๋กœ ๋‚˜๊ฐ) ์—์„œ ๋งŒ๋“  ํด๋ž˜์Šค๋ฅผ ์ธ์Šคํ„ด์Šคํ™”

            ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ ๊ตฌ๋ฌธ
            ```
            post1 = class์ด๋ฆ„() ๋˜๋Š” post1 = class์ด๋ฆ„(์—ด์š”์†Œ="๋‚ด์šฉ",์—ด์š”์†Œ2="๋‚ด์šฉ2")

            > ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ ๋ฐ ๋ณ€๊ฒฝ ๊ตฌ๋ฌธ
            

            class์ธ์Šคํ„ด์Šค.save()

            ํ•˜๋ฉด SQL์— ํ•ด๋‹น ์ธ์Šคํ„ด์Šค ์ €์žฅ, ๋˜๋Š” ๋ฐ์ดํ„ฐ ์ˆ˜์ • ์ดํ›„ ๊ทธ ๊ฐ์ฒด๋Š” ์ž์‹ ์ด ์„ค์ •ํ•œ๋งŒํผ ๋ฐ์ดํ„ฐ์†์„ฑ์„ ๊ฐ€์ง
            > ๋ฐ์ดํ„ฐ ์‚ญ์ œ ๊ตฌ๋ฌธ
            

            class์ธ์Šคํ„ด์Šค.delete() ํ•˜๋ฉด, ํ•ด๋‹น ๋ฐ์ดํ„ฐ ์‚ญ์ œ๋จ

            Post.objects.all() : Post ํด๋ž˜์Šค์˜ ๋ชจ๋“  ๊ฐ์ฒด๋ฅผ ์ถœ๋ ฅ all(1)ํ•˜๋ฉด QuerySet์˜ 1๋ฒˆ์งธ ์š”์†Œ๋ฅผ ๊ฐ€์ ธ์˜ด
            Post.objects.get() : 1๊ฐœ์˜ ๋ฐ์ดํ„ฐ ๊ฐ์ฒด๋งŒ ๊ฐ€์ ธ์˜ด, get()๋งค๊ฐœ๋ณ€์ˆ˜์— id=1ํ•˜๋ฉด id๊ฐ€ 1์ธ ๊ฐ์ฒด, title="๋‚ด์šฉ" ํ•˜๋ฉด title์•ˆ์— "๋‚ด์šฉ"์ธ ๋ฐ์ดํ„ฐ ๊ฐ์ฒด, ์ผ์น˜ํ•˜๋Š” ๊ฐ์ฒด๊ฐ€ 2๊ฐœ ์ด์ƒ ์žˆ์œผ๋ฉด ์—๋Ÿฌ๋ƒ„
            Post.objects.filter() : ๊ด„ํ˜ธ์•ˆ์— ์กฐ๊ฑด๊ณผ ์ผ์น˜ํ•˜๋Š” ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ด ex) title="hello", ์ธ ๋ชจ๋“  ๊ฐ์ฒด ๊ฐ€์ ธ์˜ด
            
            SQlite ์ต์Šคํ…์…˜ ๊น”๊ณ  SQLite explorer์—์„œ ํด๋ฆญํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ํด๋ฆญํ•  ์ˆ˜ ์žˆ์Œ
            django_extensions ํŒจํ‚ค์ง€ = ์•Œ์•„์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์ •๋ณด๋ฅผ ์ž„ํฌํŠธ ํ•ด์˜ด
            id๋Š” ์ง€์›Œ์ ธ๋„ ํ•ด๋‹น ์•„์ด๋””๋Š” ๋‹ค์‹œ ์“ฐ์ด์ง€ ์•Š์Œ,
            query= list์˜ ์„ฑ์งˆ๊ณผ ๊ฑฐ์˜ ๋น„์Šทํ•จ
            
            ### admin ์ƒ์„ฑํ•˜๊ธฐ
            

            python manage.py createsuperuser

            ์œ ์ € ๋„ค์ž„, ์ด๋ฉ”์ผ ์–ด๋“œ๋ ˆ์Šค, ํŒจ์Šค์›Œ๋“œ ์ž…๋ ฅ, ํŒจ์Šค์›Œ๋“œ ํ™•์ธ ํ›„
            

            http://์„œ๋ฒ„์ฃผ์†Œ/admin

            ์ด ๊ณณ์—์„œ ๋“ค์–ด๊ฐ€์„œ ๋กœ๊ทธ์ธ ํ•˜๋ฉด ๊ด€๋ฆฌ์ž ํŽ˜์ด์ง€๋กœ ๊ฐ
            
            from .models import ๋Œ€์ƒ ๋ชจ๋ธ
            
            ```python
            # admin.py์—์„œ 
            admin.site.register(๋Œ€์ƒ ๋ชจ๋ธ)
            
            

            ์ดํ›„ ๋‹ค์‹œ ๊ด€๋ฆฌ์ž ํŽ˜์ด์ง€๋กœ ๋“ค์–ด๊ฐ€๋ฉด ๋Œ€์ƒ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค๊ฐ€ ์˜ฌ๋ผ๊ฐ€ ์žˆ๊ณ , ๋‚ด์šฉ ํ™•์ธ ๊ฐ€๋Šฅ

            from django.shortcuts import redirect
            
            return redirect('/url/')
            # ๊ฐ€๊ณ ์‹ถ์€ ์„œ๋ฒ„๋‚ด ์›นํŽ˜์ด์ง€๋กœ ๋ณด๋ƒ„
            
            

            MODEL.objects.order_by(โ€˜์š”์†Œโ€™).all() : ํ•ด๋‹น ์š”์†Œ์˜ ์ •๋ ฌ ์ˆœ์œผ๋กœ, ๋ฐ˜๋Œ€๋กœ ์›ํ•  ๊ฒฝ์šฐ โ€˜-์š”์†Œโ€™๋กœ ๋„ฃ๊ธฐ

            QnA ๋‹ฌ๊ธฐ

            foreign key = ๋Œ“๊ธ€์ด ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์™ธ๋ž˜ ์•„์ด๋””, ์งˆ๋ฌธ์˜ id๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์„œ ํ•ด๋‹น ์งˆ๋ฌธ์— ์†ํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค

            answer ๋ชจ๋ธ ์˜ˆ์‹œ
            ```
            class Answer(models.Model):
            content = models.CharField(max_length=100)
            # CASCADE : question์ด ์‚ฌ๋ผ์ง€๋ฉด ๊ทธ ๋ฐ‘์—๋„ ๋ชจ๋‘ ์ง€์šฐ๊ฒ ๋‹ค๋Š” ์˜๋ฏธ
            question = models.ForeignKey(Question, on_delete=models.CASCADE)

            - restfullํ•œ url : ํ˜„์žฌ ๊ฒฝ๋กœ์™€ ์ž์›์ด ํ‘œ์‹œ๋˜์–ด์žˆ๋Š” url
            
            > main ํŽ˜์ด์ง€
            ```html
            {% extends 'base.html' %}
            {% block body %}
            {% for question in questions %}
            <h1>{{question.title}}</h1>
            <p>{{question.user}}</p>
            <p>{{question.content}}</p>
            <form action="/questions/{{question.id}}/answers/create/">
              <input type="text" name="content">
              <input type="submit">
            </form>
            {% for answer in question.answer_set.all %} <!--models.ForeignKey๊ฐ€ ๋งŒ๋“ค์–ด์ค€ answer_set ํ•จ์ˆ˜, ์ด๋ฅผ ํ†ตํ•ด ์ด question ๋ชจ๋ธ์„ foreignkey๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ชจ๋“  answer ๋ชจ๋ธ์„ ์ฐพ์•„์˜ฌ ์ˆ˜ ์žˆ๋‹ค.-->
            <p>{{answer.content}}</p>
            {% endfor %}
            <hr>
            {% endfor %}
            {% endblock %}
            
            

            ERD ( Entity Relationship Diagram)

            vscode = U ์•„์ง ๊นƒ์— ์•ˆ์˜ฌ๋ผ๊ฐ”๋‹ค. M : ๋ฌด์–ธ๊ฐ€ ๋ฐ”๋€Œ์—ˆ๋‹ค. A: add ๋ฌ๋‹ค.
            git add (์˜ฌ๋ฆดํŒŒ์ผ์ด๋‚˜ ํด๋”)
            git status (commitํ•œ ์ƒํƒœ ๋ณด๊ธฐ)
            git restore โ€“staged (add ์ทจ์†Œํ•  ํŒŒ์ผ)
            Nosql :

            if ๋ฌธ์„ ์ด์šฉํ•œ restfullํ•œ ์›น์ฝ”๋”ฉ

            urls.py
            ```python
            โ€ฆ
            path('add/', views.add, name="add" ), # if ๋ถ„๊ธฐ๋กœ ํ•˜๋‚˜์˜ ๊ฒฝ๋กœ๋กœ 2๊ฐ€์ง€ ๋ฐฉ์‹์˜ ์ผ์„ ์ฒ˜๋ฆฌ(์ค‘์š”)
            path('<int:id>/update/', views.update, name="update"),

            > restfull code ์˜ˆ์‹œ (create์™€ new path๋ฅผ ํ•ฉ์นœ add path)
            ```python
            def add(request): # if ๋ถ„๊ธฐ๋กœ ํ•˜๋‚˜์˜ ๊ฒฝ๋กœ๋กœ 2๊ฐ€์ง€ ๋ฐฉ์‹์˜ ์ผ์„ ์ฒ˜๋ฆฌ, form์— action=''์ด๋ฉด ์ž๊ธฐ์ž๋ฆฌ๋กœ ๋Œ์•„๊ฐ€๋Š” ๊ฒƒ์„ ์ด์šฉ(restfullํ•œ ์ฝ”๋“œ))(์ค‘์š”)
                if request.method == "POST": # method๊ฐ€ post๋กœ ๋ณด๋‚ด์ง€๋ฉด create๋กœ     
                    author = request.POST.get('author')
                    title = request.POST.get('title') # url๋กœ ๋ณด๋‚ด๋Š” ๊ฒƒ์€ ๋ฌด์กฐ๊ฑด get ๋ฐฉ์‹ 
                    content = request.POST.get('content')
                    due_date = request.POST.get('due-date')   
                    todo = Todo.objects.create(author=author, title=title, content=content, due_date=due_date)
            
                    return redirect('todos:index') # /์žˆ์œผ๋ฉด ๋ฃจํŠธ์ฃผ์†Œ์— ์ถ”๊ฐ€, ์—†์œผ๋ฉด ํ˜„์žฌ ์ฃผ์†Œ ์•ž์— ์ถ”๊ฐ€
                else:   # Get๋ฐฉ์‹์ด๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ form์œผ๋กœ ๋ฐ›๋Š” new๋กœ
                    return render(request, 'add.html')
            
            
            • django๋Š” ๋ณด๋‚ด๋Š” method๋กœ delete์™€ put์€ ์ง€์› ์•ˆํ•จ(HTTP5๋„ ์ง€์› ์•ˆํ•จ)
            • ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ์ผ๋‹จ post๋กœ ๋ณด๋‚ด๊ณ  delete put์„ ๋„ฃ์„ ๋•Œ๋Š” input type= hidden์— name=โ€™_methodโ€™, value=โ€DELETEโ€ ๋กœ ์ˆจ๊ฒจ์„œ ๋ณด๋ƒ„ (HTTP5๊ฐ€ ์ง€์› ์•ˆํ•˜๋ฏ€๋กœ)
            • restfullํ•œ ์ฝ”๋”ฉ์„ ํ•˜๋ ค๋ฉด ์ฃผ์†Œ์ฐฝ์— ๋™์‚ฌ๋Š” ๋นผ๊ณ  ๋ช…์‚ฌ๋กœ๋งŒ ์“ฐ๋ฉฐ, ๋™์‚ฌ๋Š” method ๋ฐฉ๋ฒ•์„ ๋ฐ”๊ฟ”์„œ ํ•ด๊ฒฐ
            • ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„ ์›Œํฌ๋Š” http verb๋ผ๋Š” ๊ฐœ๋…๋„ ์žˆ๋‹ค.

              add.html
              ```html
              {% extends 'base.html' %}

            {% block body %}
            <form action="" method="POST">
            {% csrf_token %}
            ์ž‘์„ฑ์ž : <input type="text" name="author">
            ์ œ๋ชฉ : <input type="text" name="title">
            ๋‚ด์šฉ : <input type="text" name="content">
            ๋งˆ๊ฐ์ผ : <input type="date" name="due-date">
            <input type="submit" value="์ €์žฅ">
            </form>
            {% endblock %}
            <!โ€“๋จ„์•ฝ ๊ธฐ๋ณธ๊ฐ’ value๋ฅผ ์ •ํ•˜๊ณ  ์‹ถ์œผ๋ฉด <input type="date" name="due-date" value="{{todo.due_date|date:'Y-m-d'}}"> ์ด๋Ÿฐ์‹์œผ๋กœ โ€“>

            - post, get ๋ฐฉ์‹์„ ์ด์šฉํ•ด ์ด ํผ(add.html) ํ•˜๋‚˜๋ฅผ ์ˆ˜์ •ํ•  ๋•Œ ์“ฐ๋Š” ํผ์œผ๋กœ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
            ## django ์ด๋ฏธ์ง€ ์—…๋กœ๋”ฉ๊ณผ ์ด๋ฏธ์ง€ ๋ฆฌ์‚ฌ์ด์ง•
            ### ์ด๋ฏธ์ง€ ๋ณด์—ฌ์ฃผ๊ธฐ
            1. ์œ„ static ๋ถ€๋ถ„์˜ favicon ๋ถ€๋ถ„ ์ฐธ์กฐ
            #### fontawesome ์ด์šฉํ•˜๊ธฐ
            1. ๋จผ์ € fontawesome ํ™ˆํŽ˜์ด์ง€์—๊ฐ€์„œ ๋กœ๊ทธ์ธํ•œ๋‹ค.
            2. ํ‚ค๋ฅผ ๋ฐœ๊ธ‰๋ฐ›๊ณ  script๋ฅผ html ํด๋”์˜ header์•ˆ์— ๋„ฃ๋Š”๋‹ค.
            ```html
            <script src="https://kit.fontawesome.com/e87731a046.js" crossorigin="anonymous"></script>
            
            
            1. ์›ํ•˜๋Š” ๊ณณ์— ์›ํ•˜๋Š” ์•„์ด์ฝ˜ ํƒœ๊ทธ๋ฅผ ์‚ฝ์ž…ํ•œ๋‹ค.
              ```html
              <i class="fas fa-chess-knight">
            ### ์ด๋ฏธ์ง€ ์—…๋กœ๋”ฉ
            1. ๋จผ์ € ์•ฑ ๋‚ด๋ถ€์˜ models.py์—์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ชจ๋ธ์„ ๋งŒ๋“ ๋‹ค.
            > models.py ํŒŒ์ผ
            ```python
            from django.db import models
            
            # Create your models here.
            class Feed(models.Model):
                content = models.CharField(max_length=150); 
                created_at = models.DateTimeField(auto_now_add=True) # ์ž๋™์œผ๋กœ ํ˜„์žฌ ๋‚ ์งœ ์ž…๋ ฅ
                image = models.ImageField() 
            
            

            -์ด๋ฅผ makemigrationsํ•˜๋ คํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์˜ค๋ฅ˜๊ฐ€ ๋œฐ ์ˆ˜ ๋„ ์žˆ๋‹ค.
            ```git bash
            You are trying to add a non-nullable field โ€˜imgโ€™ to todo without a default; we canโ€™t do that (the database
            needs something to populate existing rows).
            Please select a fix:
            1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
            2) Quit, and let me add a default in models.py
            Select an option:

            - ์ด ๋•Œ๋Š” db์—์„œ ํ•ด๋‹น ๋ชจ๋ธ์„ ๋‚ ๋ฆฌ๊ณ  ๋‹ค์‹œ makemigrationsํ•˜๋ฉด ๋œ๋‹ค. ์•ฑ ๋‚ด๋ถ€์˜ migrations ํด๋” ๋‚ด๋ถ€์˜ (ex)0001_initial.py)
            1) 
            2. 
            ### ์ด๋ฏธ์ง€ ๋ฆฌ์‚ฌ์ด์ง•
            
            ์ธ์Šคํ†จ ํ•„์š”ํ•œ ํŒจํ‚ค์ง€ : django-imagekit, Pillow, IPython
            
            
            
            ## django form์„ ์ด์šฉํ•œ ์ž๋™ ํผ ์ƒ์„ฑ
            ### django form ์„ ์–ธ
            #### models.py
            ```python
            from django.db import models
            
            # Create your models here.
            class Movie(models.Model):
                title = models.CharField(max_length=50)
                title_en = models.CharField(max_length=50)
                audience = models.IntegerField()
                open_date = models.DateField()
                genre = models.CharField(max_length=50)
                watch_grade = models.CharField(max_length=50)
                score = models.FloatField()   
                poster_url = models.TextField()
                description = models.TextField()
            
            class Comment(models.Model):
                content = models.TextField()
                movie = models.ForeignKey(Movie,on_delete=models.CASCADE)
                class Meta:
                    ordering = ('-id',) # ์ •๋ ฌ์„ id์˜ ์—ญ์ˆœ(-)์œผ๋กœ ์ถœ๋ ฅ , ,๊ผญ ํ•„์š”
            
            

            form.py

            from django import forms
            from .models import Movie, Comment
            
            class MovieForm(forms.Form): # forms.Form ์ƒ์†
                title = forms.CharField(max_length=50)
                title_en = forms.CharField(
                                max_length=50,
                                label="์˜๋ฌธ ์ œ๋ชฉ", # ๊ธฐ๋ณธ๊ฐ’์—์„œ ์›ํ•˜๋Š” ๋ผ๋ฒจ์ด๋ฆ„ ๋ฐ”๊ฟ”์คŒ
                                widget=forms.TextInput(
                                    attrs={
                                        'placeholder': '์˜๋ฌธ์ œ๋ชฉ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”',
                                    }
                                )
                            )
                audience = forms.IntegerField()
                open_date = forms.DateField(widget=forms.DateInput(attrs={'type':'date'}))
                genre = forms.CharField(max_length=50)
                watch_grade = forms.CharField(max_length=50)
                score = forms.FloatField()   
                poster_url = forms.CharField(widget=forms.Textarea) # textarea๋กœ ๋ฐ”๊ฟ”์คŒ, django๊ฐ€ charfield๋ฅผ ๊ธฐ๋ณธ์œผ๋กœ ์žก๊ณ  ์žˆ์–ด์„œ ์ด๊ฑฐ ์จ์•ผํ•จ
                description = forms.CharField(widget=forms.Textarea)
                # widget: ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•์„ ํ•˜๊ฒŒ ํ•ด์คŒ attrs, html tag์— ๊ฐ’์„ ์ถ”๊ฐ€ํ•ด์คŒ
            
            class MovieModelForm(forms.ModelForm): # Model์— ๊ด€๊ณ„์žˆ๋Š” Form์œผ๋กœ ์ƒ์†, ์ž๋™์œผ๋กœ ๋ชจ๋ธ ๋‚ด๋ถ€์˜ column ๋งŒํผ ํผ์„ ๋งŒ๋“ค์–ด์คŒ
                open_date = forms.DateField(widget=forms.DateInput(attrs={'type':'date'})) # ์ด๋Ÿฐ ๋ฐฉ๋ฒ•์œผ๋กœ ์ผ๋ถ€๋Š” ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ๋งŒ๋“ค์–ด๋‚ผ ์ˆ˜ ์žˆ์Œ ์˜ค๋ฒ„๋ผ์ด๋”ฉ?    
                class Meta: # ์†์„ฑ์œผ๋กœ ๋งŒ๋“ค๋ฉด column์œผ๋กœ ์ธ์ง€ํ•˜๋ฏ€๋กœ class ๊ฐ์ฒด๋กœ ๋งŒ๋“ค์–ด์•ผ ํ•จ
                    model = Movie # ๋ชจ๋ธ ์ž…๋ ฅ
                    fields = '__all__' # ์ „๋ถ€
            
            class CommentModelForm(forms.ModelForm):
                class Meta:
                    model = Comment
                    fields = ('content',) # ์ถœ๋ ฅํ•  ๋ถ€๋ถ„๋งŒ tuple๋กœ ๋„ฃ์–ด์ฃผ๋ฉด ๋จ, ๋์— ',' ๋ฌด์กฐ๊ฑด ๋„ฃ์–ด์•ผํ•จ
            
            
            • ์ด๊ฒƒ์„ ์ด์šฉํ•˜์—ฌ form์„ ์ž๋™ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
            • ModelForm์„ ์ด์šฉํ•˜๋ฉด form input ์š”์†Œ ๋˜ํ•œ ์ž๋™์œผ๋กœ ๋งŒ๋“ค์–ด ์ค€๋‹ค.

              django form ์ด์šฉ

              form.html

              ```html
              {% extends 'base.html' %}
              {% load bootstrap4 %}
              {% block body %}
              {% if request.resolver_match.url_name == "create_model_form" %} {% comment %} ํ˜„์žฌ ์‚ฌ์ดํŠธ๋กœ ์ •๋ณด๋ฅผ ๋ณด๋‚ธ views.py์—์„œ ์ •์˜ํ•œ ํ•จ์ˆ˜ ์ด๋ฆ„์„ ๊ฐ€์ ธ์˜ด {% endcomment%}
              <h1>Create</h1>
              {% else %}
              <h1>Update</h1>
              {% endif %}
              <form action="" method="POST">
              {% csrf_token %}
              {% bootstrap_form form %}
              {% buttons submit="์ œ์ถœ" %}
              {% endbuttons %}

              {% comment %}
              # html {{form.as_p}}ํ•˜๋ฉด pํƒœ๊ทธ๋กœ ๋ฌถ์—ฌ์„œ ์ถœ๋ ฅ๋จ
              # as_ul ํ•˜๋ฉด ul ํƒœ๊ทธ๋กœ ๋ฌถ์—ฌ์„œ ์ถœ๋ ฅ๋จ
              # as_table * table ํƒœ๊ทธ์•ˆ์— ๋„ฃ์œผ๋ฉด * ํ…Œ์ด๋ธ” ํ˜•ํƒœ๋กœ ์ถœ๋ ฅ
              # {{form.title.label_tag}} ํ•˜๋ฉด ํ•ด๋‹น ์š”์†Œ ์ด๋ฆ„์˜ label์ด ์ƒ๊น€

              <table>
              {{form.as_table}}
              </table>
              <input type="submit">
              {% endcomment %}

              </form>
              {% endblock %}

            #### base.html
            ```python
            {% load bootstrap4 %} {% comment %} ํ˜„์žฌ ํŽ˜์ด์ง€์—์„œ๋งŒ ๋™์ž‘ํ•จ ๋‹ค๋ฅธ block์€ extends ์•„๋ž˜ block์œ„์—์„œ ํ•  ๊ฒƒ {% endcomment%}
            <!DOCTYPE html>
            <html lang="ko">
            <head>
              <meta charset="UTF-8">
              <meta name="viewport" content="width=device-width, initial-scale=1.0">
              <meta http-equiv="X-UA-Compatible" content="ie=edge">
              <title>formmovie</title>
              {% bootstrap_css %}
            </head>
            <body>
              <a href="{% url 'movies:index' %}">ํ™ˆ</a>
              <a href="{% url 'movies:create' %}">๊ธ€์“ฐ๊ธฐ</a>
              <a href="{% url 'movies:create_model_form' %}">๊ธ€์“ฐ๊ธฐ(๋ชจ๋ธํผ)</a>
              <div class="container">
            
                {% block body %}
                {% endblock %}
              </div>
              {% bootstrap_javascript jquery='full' %}
            </body>
            </html>
            
            
            • pip install django-bootstrap4 ์ดํ›„, settings.py์˜ INSTALLED_APPS์— โ€˜bootstrap4โ€™,๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ , {% load bootstrap4 %}๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ์‚ฌ์šฉํ•œ๋‹ค.
            • ์ด์™ธ์—๋„ {% bootstrap_javascript jquery=โ€™fullโ€™ %}, {% bootstrap_css %}๋ฅผ ๊ฐ๊ฐ body์™€ header์— ์ถ”๊ฐ€ํ•˜์—ฌ์•ผ ํ•œ๋‹ค.
            • {% comment %} ๋ฅผ ์ด์šฉํ•˜๋ฉด DTL์ด ๋ฌด์‹œํ•˜๋Š” ์ฃผ์„์„ ๋‹ฌ ์ˆ˜ ์žˆ๋‹ค.{% endcomment%}

              detail.html

              ```python
              {% extends 'base.html' %}
              {% load bootstrap4 %}
              {% block body %}
              <br>
              {{movie.title}}
              {{movie.title_en}}
              {{movie.audience}}
              {{movie.open_date}}
              {{movie.poster_url}}
              <form action="{% url 'movies:delete' movie.id %}" method="POST">
              {% csrf_token %}
              <input type="submit" value="์‚ญ์ œ(post)">
              </form>
              {% comment %}
              <a href="{% url 'movies:delete' movie.id %}">์‚ญ์ œํ•ด๋ผ ์• ์†ก์ด</a>
              ์š”๊ฒƒ์€ ์ฃผ์„ ๋‹ค๋Š”๋ฐฉ๋ฒ•
              {% endcomment %}
              <a href="{% url 'movies:update' movie.id %}">์ˆ˜์ •</a>
              <a href="{% url 'movies:update_model_form' movie.id %}">์ˆ˜์ •(๋ชจ๋ธํผ)</a>
              {% for comment in movie.comment_set.all %}
              {{comment.content}}
              <a href="{% url 'movies:comment_delete' movie.id comment.id %}">์‚ญ์ œ</a>
              <br>
              {% endfor %}
              <form action="{% url 'movies:comment_create' movie.id %}" method="POST">
              {% csrf_token %}
              {% bootstrap_form comment_form %}
              {% comment %}
              forms.py์—์„œ field=(content,) ๋„ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ
              ์ด๋ฐฉ๋ฒ•๋„ ๋จ
              {% bootstrap_form comment_form exclude='movie'%}
              {% endcomment %}
              {% buttons submit="์ œ์ถœ" %}
              {% endbuttons %}
              </form>
              {% endblock %}

            #### views.py
            ```python
            from django.shortcuts import render, redirect, get_object_or_404
            from .forms import MovieForm, MovieModelForm, CommentModelForm
            from IPython import embed # ์›น ๋””๋ฒ„๊น…์šฉ
            from .models import Movie, Comment
            # Create your views here.
            def index(request):
                movies = Movie.objects.all().order_by('-id') # all() ์ƒ๋žต๊ฐ€๋Šฅ
                context = {
                    'movies': movies
                }
                return render(request, 'index.html', context)
            
            def create(request):
                if request.method == "POST":
                    form = MovieForm(request.POST)       
                    if form.is_valid(): # ๋ฐฑ์—”๋“œ์—์„œ ํ•œ๋ฒˆ ๋” ๊ฒ€์ฆ
                        movie = Movie() # form.cleaned_data : ๊ฒ€์ฆ์ด ์™„๋ฃŒ, ๊ฐ€๊ณต์ด ์™„๋ฃŒ๋œ ๋ฐ์ดํ„ฐ (์•ž์˜ ๋นˆ๊ณต๊ฐ„์„ ์ง€์šฐ๋Š” ๋“ฑ์˜ ํ–‰๋™)
                        movie.title = form.cleaned_data.get('title')
                        movie.title_en = form.cleaned_data.get('title_en')
                        movie.audience = form.cleaned_data.get('audience')
                        movie.open_date = form.cleaned_data.get('open_date')
                        movie.genre = form.cleaned_data.get('genre')
                        movie.watch_grade = form.cleaned_data.get('watch_grade')
                        movie.score = form.cleaned_data.get('score') 
                        movie.poster_url = form.cleaned_data.get('poster_url')
                        movie.description = form.cleaned_data.get('title_en')
                        movie.save()
                        return redirect('movies:index')
                else:
                    form = MovieForm()
                context = {
                    'form' : form
                }
                return render(request, 'form.html', context)
            
            def detail(request, id):
                # movie = Movie.objects.get(id=id)
                movie = get_object_or_404(Movie, id=id) # ์ž˜๋ชป๋œ ์ ‘๊ทผ์ด๋ฉด 404 ์—๋Ÿฌ๋ฅผ ๋œจ๊ฒŒ ํ•ด์คŒ
                comment_form = CommentModelForm()
            
                context = {
                    'movie': movie,
                    'comment_form': comment_form,
                }
                return render(request, 'detail.html', context)
            
            def delete(request, id):
                movie = get_object_or_404(Movie, id=id)
            
                if request.method == "POST": # POST ์š”์ฒญ์ผ ์‹œ์—๋งŒ ์‚ญ์ œ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋„๋ก ๋งŒ๋“ฆ (์ฆ‰ url์„ ํ†ตํ•œ ์ ‘๊ทผ์ด ์•„๋‹Œ ์ •์ƒ์ ์ธ ์ ‘๊ทผ์ผ์‹œ)
                    movie.delete()
                    return redirect("movies:index")
                else:
                    return redirect("movies:detail", id)
            
            def update(request, id):
                movie = get_object_or_404(Movie, id=id)
                if request.method == "POST":
                    form = MovieForm(request.POST)
                    if form.is_valid():
                        movie.title = form.cleaned_data.get('title')
                        movie.title_en = form.cleaned_data.get('title_en')
                        movie.audience = form.cleaned_data.get('audience')
                        movie.open_date = form.cleaned_data.get('open_date')
                        movie.genre = form.cleaned_data.get('genre')
                        movie.watch_grade = form.cleaned_data.get('watch_grade')
                        movie.score = form.cleaned_data.get('score') 
                        movie.poster_url = form.cleaned_data.get('poster_url')
                        movie.description = form.cleaned_data.get('title_en')
                        movie.save()
                        return redirect('movies:detail', id)
                else:
                    form = MovieForm(initial=movie.__dict__) # initial๊ณผ ํ•ด๋‹น ๊ฐ์ฒด์˜ __dict__๋ฅผ ์ด์šฉํ•ด ๊ธฐ์กด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Œ
                context = {
                    'form': form,
                }
                return render(request, 'form.html', context)
            
            def create_model_form(request):
                if request.method == "POST":        
                    form = MovieModelForm(request.POST)
                    if form.is_valid():
                        movie = form.save() # form.save()๋Š” movie ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค.
                        return redirect('movies:detail', movie.id)
                else:
                    form = MovieModelForm()
                context = {
                    'form': form
                }
                return render(request, 'form.html', context)
            
            def update_model_form(request, id):
                movie = get_object_or_404(Movie, id=id) # Movie ๋ชจ๋ธ์˜ id๊ฐ’์ด id์ธ ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์™€๋ผ
                if request.method == "POST":
                    form = MovieModelForm(request.POST, instance=movie) # ์ด๋Ÿฐ ๋ฐฉ๋ฒ•์œผ๋กœ ๊ณผ๊ฑฐ์˜ ์ •๋ณด์™€ ์ˆ˜์ •๋œ ์ดํ›„์˜ ์ •๋ณด๋„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Œ
                    if form.is_valid(): # ์ด๋ฅผ ํ†ตํ•ด ๊ทธ ๋‘๊ฐ€์ง€ ์ •๋ณด๋ฅผ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ์Œ
                        form.save()
                        return redirect('movies:detail', id)
                else:
                    form = MovieModelForm(instance = movie) # modelForm์„ ์ƒ์† ๋ฐ›์€ form์€ instanace๋กœ ํ•ด์•ผํ•จ
            
                context = {
                    'form': form
                }
                return render(request, 'form.html', context)
            
            def comment_create(request, movie_id):
                movie = get_object_or_404(Movie, id=movie_id)
                if request.method == "POST":
                    form = CommentModelForm(request.POST)
                    if form.is_valid():
                        comment = form.save(commit=False) # ๋ฐ”๋กœ saveํ•˜์ง€ ์•Š๊ณ  ๊ธฐ๋‹ค๋ฆผ
                        comment.movie = movie # movie ์ •๋ณด ์ฃผ์ž…
                        comment.save() # saveํ•จ
                        return redirect('movies:detail', movie_id)
                    else:
                        return redirect('movies:detail', movie_id)
                else:
                    return redirect('movies:detail', movie_id)
            
            def comment_delete(request, movie_id, comment_id):
                comment = Comment.objects.get(id=comment_id)
                comment.delete()
                return redirect('movies:detail', movie_id)
            
            #
            
            
            • POST ์ ‘๊ทผ๊ณผ GET ์ ‘๊ทผ์˜ ์ฐจ์ด๋ฅผ ์ด์šฉํ•˜์—ฌ validํ•œ ์ ‘๊ทผ ๊ตฌ๋ณ„๊ฐ€๋Šฅ
            • Form์„ ์ด์šฉํ•˜์—ฌ update๊ตฌํ˜„