본문 바로가기

TIL

[TIL 2024. 04. 11] Django 프로젝트 순서 정리

장고 기초 강의를 들으면서 코드를 작성해보는데, 앱별로 분리한 이후의 흐름이 정리가 안되고 헷갈리는 느낌이다.

그래서  가상환경 생성부터 일련의 과정을 쭉- 정리해보기로 했다.

 

Django 프로젝트 순서 정리

(0. 파이썬 설치)

1. 가상환경 생성

더보기
  • python -m venv .venv

 

2. 가상환경 활성화

더보기
  • source .venv/Scripts/activate

 

3. 장고(django) 설치

더보기
  • pip install django==4.2
  • pip list

 

4. 의존성 파일 생성

더보기
  • pip freeze > requirements.txt
  • pip install  -r requirements.txt  (#만들어진 requirements.txt 읽어오기)

 

5. 프로젝트 생성

더보기
  • django-admin startproject <프로젝트명>
  • django-admin my_pjt

 

  • django-admin startproject <프로젝트명> .
  • django-admin startproject my_pjt . (#겉껍질 없이 바로 inner 파 생성)

 

6. (서버 실행)

더보기
  • cd my_pjt
  • python manage.py runserver

 

7-1. 앱 생성

더보기
  • python manage.py startapp <app 이름>
  • python manage.py startapp articles

 

7-2. 앱 등록

  • settings.py의 INSTALLED_APPS에 등록(트레일링 콤마까지!)

 

8. MTV 패턴 중 TV만 우선 연결

 

즉, HttpRequest -> URLs -> View -> Template -> View -> HttpResponse의 흐름이다.

  • urls.py에서 경로 확인 설정
    • urlpatterns에 경로 추가: path
    • urls.py는 프로젝트 디렉토리에, views.py는 앱 디렉토리에 있음: from articles import views
  • views.py에서 view함수 정의
    • view함수는 request를 매개변수로 받음(정확히는 HttpRequest를 첫번째 인자로 받는 것.)
    • HttpResponse("문자열"): from django.http import HttpResponse
    • render(request, html이름(template), context, etc..)
    • render시에는 context를 dict 형태로 넘길 수 있음
    • context에서 key는 항상 문자열('')이다..!
  • app 디렉토리 내의 templates디렉토리에 (view함수에서 render한) html 생성
    • templates의 기본경로: app_name / templates
    • 즉, 각 app 디렉토리 내에는 각 templates디렉토리가 있다
    • (cf. BASE DIR위치의 templates와 혼동하지 말 것!)
    • settings.py의 TEMPLATES항목의 APP_DIRS: True를 통해 장고가 template을 찾음
      • APP_DIRS: True (장고야, 각 app디렉토리 내에 templates디렉토리 넣어뒀어, 거기도 뒤적거려줘!)
      • settings.py의 TEMPLATES에서 DIRS는 추후에 BASE DIR / templates를 추가하는데 사용함. 즉, 커스텀 template의 경로를 추가해주는 것임.
    • #
    • 처음에는 html 자동완성
    • 추후에는 '상속' 활용: base.html (BASE DIR에 있는 templates디렉토리)
    • DTL 활용 (변수, 태그, 필터, 주석)

 

9. template 상속 (-> template(html)들을 정리해줌)

  • 코드 중복 해결, 코드의 재사용성
  • 다중상속을 지원하지 않음
    • extends는 하나의 html내에서 한번만 가능.
    • 하지만 base.html을 상속한 test.html이 있다고 할 때, 새로운 html에서 test.html자체를 상속받는(extends) 방식도 가능하다
  • 상위 template인 'base.html'에 공통된 부분을 정의하고, 하위 template에서 달라질 부분은 block으로 만듦
    • base.html은 BASE DIR 위치에 templates디렉토리 내에 위치 (BASE DIR == 프로젝트 디렉토리 내 최상단)
    • 하위 template들은 각 app디렉토리 내의 templates디렉토리 내에 위치
    • block지정은 template tag(DTL)를 사용함
    • endblock은 블록명을 지정하지 않아도 동작에는 지장이 없으나, block이 많아질 경우를 대비해서 블록명을 함께 명시하는 습관을 들이는 게 좋다
더보기
  • {% extends '<template_name>' %}
  • {% extends 'base.html' %}   #예시
  • #template_name시에 따옴표 주의!
  • #
  • {% block <block명> %}
  • {% endblock <block명> %}
  • {% block content %}  #예시
  • {% endblock content %}  #예시
  • 커스텀 template인 BASE DIR위치의 templates디렉토리를 settings.py의 DIRS에 추가해줘야 함.

 

10. (form태그 사용 연습)

 

즉, Data-Throw로 URLs, View, html(template)작성하고, form태그로 Data-Catch로 보냄(처음에는 하드코딩==경로 직접 명시, 아직 URL name사용 전..)

Data-Catch로 URLs, View, html(template)를 작성해줌

 

구체적으로는 data-throw URLs로 요청들어옴-> url에서 views.data-throw로 보냄-> view함수로 data-throw.html 렌더해줌.

data-catch에서 받은 입력값을 form태그로 data-catch URLs로 보내줌 -> url에서 views.data-catch로 보냄 -> view함수로 data-catch에서 데이터 input값들 받아서(request.GET.get('input name명') context로 data-catch.html에 넘겨줌 -> contexf로 받은 데이터를 html에 뿌려줌..

 

  • Data-Throw와 Data-Catch 경로, view함수, template등을 각각 만들어주고 form태그로 데이터 주고받아 보기
  • form태그에서 가장 중요한 것은 action, method, 그리고 name임.
    • action을 지정하지 않으면 디폴트값인 '현재 페이지'로 input받은 데이터를 전송됨
    • method를 지정하지 않으면 디폴트값인 'GET'으로 요청을 보냄
    • name이 key가 되고, input으로 받는 내용이 val이 됨
  • form태그로 label, input, button 등을 감싸야 함
  • label태그의 forinput태그의 id로 서로 바인딩 해주면 좋다 (라벨만 눌러도 input에 커서가 가도록)
  • input태그의 type은 다양하다. text, date, password등. (여러 줄의 입력을 받아야 하면 "textarea태그"를 사용하면 됨)
    • input태그의 type을 지정하지 않으면 디폴트값인 'text'로 인식한다. 즉, type=text
  • button의 type은 반드시 'submit'으로 해야 한다

 

11. a태그(하이퍼링크) 및 URLs name 활용

  • 각 페이지를 오고 가기 편하게 a태그로 하이퍼링크를 추가해준다
  • URLs name을 사용하지 않으면 하드코딩임..즉, 모든 경로를 직접 적어줘야 하는데, 추후에 다중app으로 분리하고 나면 url이 복잡해지면 경로를 직접 적어주는 것은 오류의 가능성이 너무 높다. 따라서 URLs name을 사용하면 하드코딩의 번거로움을 없애고, 오류의 가능성을 방지할 수 있다.

 

12. URL dispatcher와 variable routing

  • URL dispatcher는 들어온 요청을 어느 view로 보내서 처리하게 할지 정하는 곳을 말한다
  • Users/Amy와 Users/aiden처럼 바뀌는 부분만 변수로 처리하기: Users/변수/
  • 즉, 하나의 URL에 여러개의 페이지를 연결하는 것
    • 회원마다 마이페이지(프로필페이지)를 달리 출력: 페이지 자체의 html은 동일하나, 로그인으로 들어오는 변수(회원명 등)만 따로 처리함. 즉, 하나의 url로 회원마다 바뀐 부분이 있는 html을 출력함.
    • 중요한 것은 바뀌는 부분만 '변수'로 받아서 -> view함수에 매개변수로 넘겨줘서 처리한다는 것!
    • 더보기
      #urls.py
      path("users/<str:username>, views.profile, name="profile")

      #views.py
      def profile(request, username):
          return render(request, 'profile.html')

 

 

13. 다중 앱 구현

  • 각 app마다 urls.py, views.py, templates디렉토리가 있도록 분리하는 것
  • 그러니까 구조가 각 app마다 위의 요소가 각각 있고, BASE DIR에는 base.html이 있는 templates디렉토리가 별도로 있음.
  • 각 app디렉토리마다 urls.py(파일)를 새로 생성해주고, 기본세팅 해주기: 기본세팅없이 내용을 비워두면 오류남.
    • 더보기
      # urls.py (in 각 app 디렉토리)
      from django.urls import path
      urlpatterns = [
      ]
    • 더보기
      #urls.py (in 프로젝트 디렉토리)
      form django-urls import path, include
      urlpatterns = [
             path('articles/', include('articles.urls')),
             path('users/', include('users.urls'))
      ]
  • 다중 app으로 각 app들을 분리한 후에_url요청 경로를 보거나 생성할 때 가장 중요한 점은 항상 프로젝트 디렉토리 내에 있는 urls.py를 가장 먼저 봐야한다는 것이다. 여기서 우선적으로 순서대로 읽어내려가며 처리가 이루어지기 때문이다.
  • 만약 url요청이 users/profile/Amy로 들어온 경우, 프로젝트 디렉토리의 urls.py는 users 까지만 등록되어 있는 path와 일치하는지 확인하고, 일치한다면 뒤의 profile/Amy는 해당 users앱의 urls.py에서 처리하도록 보낸다.
  • 또 다른 예로 articles/라는 url로 요청이 들어오는 경우라면
  • 더보기
    #urls.py (in 프로젝트 디렉토리)
    from django-urls import path, include
    urlpatterns = [
        path('articles/', include('articles.urls')),
        path('users/', include('users.urls')),
    ]
  • 더보기
    #urls.py (in 앱 디렉토리 _여기서는 users디렉토리의 urls.py)
    from django-urls import path
    urlpatterns = [
        path('', veiws.articles, name="articles")
    ]

위와 같이, users디렉토리 내의 urls.py에서는 ''처럼 따옴표 안이 비어있어야 한다.

왜냐하면 들어온 요청의 url이 'articles/'이므로, 이 부분은 이미 프로젝트 디렉토리 내의 urls.py에서 일치 여부를 확인하고 일치해서 users앱의 urls.py로 넘겨준 것이므로 더 이상 맞춰볼 url이 없기 때문이다.