본문 바로가기
Always Awake/Django 기본 정리(20.01.14~)

Django Girls Tutorial - 20.01.14~15

by 욕심많은알파카 2020. 1. 15.

1. 웹의 작동원리

 

인터넷은 수많은 기계들이 연결된 네트워크로, 만약 내가 원하는 지점으로 이동하고 싶다면 다른 수많은 기계들을 통과해야 한다.

 

웹사이트 보기위해 네트워크에 요청하는것은 편지를 보내는 것과 같아서, 편지(데이터 패킷)을 보내면 수많은 우체국(라우터)를 거쳐서 전달된다. 전달방식은 라우터마다 상이하다.

 

편지를 보내는 규칙이 제대로 되어있어야 편지가 제대로 배달되는것과 같이, 데이터패킷에도 올바른 규칙이 적용되어야 하는데, 현재 우리가 사용하고 있는 규칙이 바로 HTTP(Hypertext Transfer Protocol)이다.

 

즉, 데이터패킷을 HTTP에 따라 작성해서 네트워크에 요청(request)하면, 해당 웹사이트가 동작할 서버(기계)에서 그 패킷을 받고, 다시 웹사이트의 내용(다른 데이터패킷)으로 되돌려준다(response).

 

2. django 초기 파일

장고 프로젝트 시작시 만들어지는

 

manage.py —> 사이트 관리를 도와주는 스크립트. 다른 설치작업 없이 컴퓨터에서 바로 웹서버를 실행 할 수 있게 도와줌

settings.py —> 웹사이트 설정이 있는 파일

urls.py —> urlresolver가 사용하는 패턴목록을 포함하고 있음. 데이터패킷을 어느곳으로 전달할지 urlresolver가 판단하도록 도와주는 파일

 

세 파일들은 함부로 수정하거나 삭제하면 안된다.

 

3. 호스트값의 초기 설정

setting.py의

 

debug = True고

Allowed Host = [] 로 비어있으면

 

호스트는 ‘localhost’, ‘127.0.0.1’, ‘[::1]’에 대해서 유효하다.

localhost : 루프백 호스트명으로, 자신의 컴퓨터를 의미한다.

127.0.0.1 : IPv4에서 local host의 IP주소를 의미한다.

::1 : '0:0:0:0:0:0:0:1'의 약자로, IPv6에서 local host의 IP주소를 의미한다.

 

즉, debug = True고 Allowed Host가 비어있으면 웹페이지를 들어갈 수 있는 컴퓨터는 localhost, 자신의 컴퓨터뿐이라는 말이다.

 

4. runserver 중 명령어의 입력

 

터미널에서 manage.py를 runserver하고 있는 동안에는 새로운 명령어 프롬프트가 표시되지 않는다.

터미널이 서버에 들어오는 요청을 수신대기하기 위해 작동중이기 때문.

해당 터미널은 서버를 돌리는데에만 사용된다고 보면된다.

 

만약 명령어를 입력하고싶다면 서버run을 멈추든지, 새 터미널을 열든지.

 

5. models의 필드

CharField : 글자수가 제한된 텍스트 (제목같은 짧은 문자열)

TextField : 글자수에 제한이 없는 긴 텍스트

DateTimeField : 날짜와 시간

ForeignKey : 다른 모델에 대한 링크

 

이외에는 (https://docs.djangoproject.com/en/2.0/ref/models/fields/#field-types)참조

 

6. migrate의 의미

앱을 추가하고 난 뒤 모델을 정의하고나서, (또는 앱 내의 파일 중 무언가를 변화시켰을때)

 

python manage.py make migrations 앱이름

 

위의 명령어를 통하여 manage.py가 앱에서 어떤 변화가 생겼다는 것을 감지하고 반영할 수 있도록 migration file을 만든다.

이후에

 

python manage.py make migrate 앱이름

 

위의 명령어를 통하여 미리 만들어둔 migration file을 실제로 반영한다.

 

7. URLconf (URL configuration)

request가 들어왔을 때 장고에서 해당 URL과 일치하는 뷰를 찾기 위한 패턴들의 집합.

 

urls.py에 있는 urlpatters 리스트는 해당 url을 특정 view로 연결해주는 path들이 모여있음.

자세한 내용은 장고 문서 urls파트(https://docs.djangoproject.com/en/2.2/topics/http/urls/)참조

 

프로젝트의 urls.py에 app의 view로 가는 path를 전부 지정해 놓으면 너무 길어지고 지저분해지기 때문에,

일반적으로 앱의 urls.py에 path를 지정해놓고 —> 프로젝트의 urls.py에서 앱의 urls.py의 url들을 가져오는 형식을 취한다.

 

이 경우 프로젝트의 urls.py 내의 urlpatterns에

 

path( ‘앱의 view로 넘겨줄 URL주소’, include(‘앱이름.urls’))

 

를 추가한다.

 

이 때 path에 명시된 URL은 전체 URL 경로 중 사이트명에 해당하는 도메인명 (ex-https://google.com)을 무시하고 도메인명 이후에 붙는 파일경로(ex- /member/mem.jsp)이다.

 

전체 URL 경로 = 도메인명(프로토콜 식별자+호스트주소+포트번호) + 파일 경로(path) + query + reference

 

 

8. View

urlspatterns에서 특정 view로 가는 path를 지정해주었다면, 당연히 view를 만들어 놓아야 한다.

 

view.py에서, 함수형 view와 class형 view로 나누어 view를 만들어주게 되는데,

view의 역할은 다음과 같다.

 

URL을 통해 들어온 request 객체를 인자로 받는다—>템플릿에서 형식을, 모델에서 DB안의 정보를 가져와 requeset를 보낸 브라우저로 전송할 response를 render 함수를 통하여 반환한다.

 

 

9. Template

view만으로도 response를 전달할 수 있지만, 정보를 전달하는 형식을 명확히 하고 시각적으로 아름답게 하기 위해 html과 css를 이용한 template을 사용한다.

 

앱 내에 ‘templates’ 폴더를, 다시 그 ‘template’폴더 내부에 ‘앱이름’ 폴더를 다시 만들고 그 안에 template(html+css)를 저장한다.

해당 파일의 경로를 view.py의 render 함수 내에 인자로 명시해주면 view가 해당 템플릿을 참조하여 response를 생성한다.

 

10. QuerySet(쿼리셋)

전달받은 모델의 객체 목록으로, DB로부터 데이터를 읽고 필터를 걸거나 정렬한다.

 

manage.py의 shell(장고 interactive console)로 들어간 뒤, 앱.models에서 원하는 모델명을 import한다.

—> 해당 모델의 현존하는 객체 리스트에 접근하고, 수정/삭제하거나 추가할 수 있다.

django.contrib.auth.models에서 User를 import한다.

—> 해당 프로젝트에 등록된 user 모델의 객체리스트에 접근하고, 수정/삭제하거나 추가할 수 있다.

이외에도 원하는 모델이나 모듈을 임포트 해 쿼리셋을 이용하여 접근할 수 있다.

 

Django interactive console에서 나오고싶다면 exit()를 입력하면 된다.

 

요악하자면, 쿼리셋은 Django DB용 내장 SQL라고 볼 수 있다.

 

view에서 model을 받을때, 모델의 객체들을 쿼리셋으로 가공한 객체 리스트를 새 객채에 할당하고, 해당 객체를 render함수에 인자로 제공한다.

ex)

def post_list(request):

    posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') #DB의 내용을 가져온 쿼리셋객체 할당

    return render(request, 'blog/post_list.html', {'posts': posts}) #렌더함수에 posts라는 쿼리셋객체 제공

 

이를 통해 template에 동적 데이터를 전달할 수 있다(DB에서 어떤 쿼리로 뽑아오느냐에 따라 데이터가 바뀌므로)

 

 

11. 탬플릿 태그(template tags)

html은 정적이지만, 파이썬은 동적이다. 그렇다면 웹사이트에 사용자의 요청이나 상황에 따라 바뀌는 동적 컨텐츠를 제공하려면 html에 파이썬을 끼워넣으면 되지 않을까?

 

그러나 html에 파이썬 코드를 넣어도 파이썬 코드는 작동하지 않는다. 브라우저는 html밖에 이해할 수 없게 설계되어있기 때문이다.

이 때 탬플릿 태그를 이용하여 html내에 파이썬코드를 html로 변환할 수 있다. 이를 통해 빠르고 쉽게 동적인 웹사이트를 만들 수 있다.

 

형식은 이렇다.

 

{% 태그명 %}

 

 

12.템플릿 확장(template extending)

웹사이트 내에서 다른 페이지로 이동할 때, html구조의 일부만 바꾸고 나머지는 그대로 재사용하고싶은 경우가 있다.

 

예를 들어, 일반적인 웹사이트에서 배너부분이나 메뉴바부분을 바꾸지 않고, container에 담은 메인 컨텐츠 구성방식만 바꾸고싶다고 하자.

이 경우에 각페이지마다 html을 따로 지정하여 템플릿을 각각 사용하는것은 낭비이고, 귀찮기도 하다. 또, 템플릿을 수정할 일이 생겼을 때 매번 모든 템플릿을 고쳐주는 것도 고역일 것이다.

 

템플릿 확장을 사용하면 원래 있던 템플릿의 부분을 참조하여 재사용할 수 있다. 따라서 유지보수가 빠르고 간편하며, 웹페이지의 추가 시에도 재사용 부분을 만들 필요가 없으므로 품이 덜든다고 할 수 있다.

 

사용 방법은 다음과 같다.

 

  • base가 되는 html템플릿을 만들고 재사용 될 부분들을 만들어준다.
  • base 템플릿 내에서 동적으로 바뀔 부분에 block content태그를 사용한다.
  • block content내에 들어갈 내용들만을 담은 템플릿을 따로 만들어주고 해당 html 템플릿 최상단에 extends 베이스템플릿 태그를 추가한다.

 

 

13. pk = 모델명.pk

pk란 DB의 레코드를 식별하는 기본 키(Primary Key)의 준말이다.

 

어떤 모델에서 기본키를 따로 정하지 않으면, 장고는 pk라는 필드를 추가해 모델에서 새로운 객체가 생성될 때마다 그 값이 1,2,3 등으로 증가한다. 해당 객체의 다른 필드에 접근하는 것처럼 모델명.pk를 사용해서 기본키에 접근할 수 있다.

 

 

14. 폼(form)

 

웹사이트에 접속하여 특정 정보를 모델에 저장하여 남기고싶을때 (ex-포스팅을 저장) django의 폼을 이용하여 저장한다.

폼을 작성하기 위해 폼을 작성할 공간이 들어가는 템플릿을 만들어두고, 해당 url도 지정하여 path로 추가한다.

이후 view.py로 가서, 폼이 작성되지 않았다면 폼을 작성할 수 있는 화면을 열어주는 렌더를 반환하고, 폼이 작성되었다면 모델에 내용을 저장해 객체를 만들고 해당 객체로 리다이렉트시켜주는 view를 만든다.

 

view의 예시는 다음과 같다.

 

def post_new(request):
    #만약 페이지 내에서 폼에 내용을 작성하고 save버튼을 눌렀다면
    if request.method == "POST":
        form = PostForm(request.POST)
        if form.is_valid():
            post= form.save(commit=False) #아직 작성자(author)를 추가안했으므로 폼을 미리 저장하지 말라는 코드
            post.author = request.user
            post.published_date = timezone.now()
            post.save()
            #폼이 정상적으로 저장되었다면 --> post모델에 객체로 추가되었을 것이므로 해당 pk를 이용해 해당 포스팅의 url주소로 보내준다.
            return redirect('post_detail', pk=post.pk)
    #만약 페이지 내에서 폼에 아직 작성 저장을 하지 않았다면
    else:
        form = PostForm()
    #save버튼을 아직 안눌렀으므로 edit템플릿위에 폼을 쓸 수 있게 렌더 반환해준다.
    return render(request, 'blog/post_edit.html', {'form' : form})

 

 

수정하는 예시는 다음과 같다.

 

def post_edit(request, pk):
    post = get_object_or_404(Post, pk=pk)
    #폼을 수정하여 다시 save를 눌렀다면
    if request.method == "POST":
        #수정하고자 하는 글의 Post모델 instance를 일단 가져와서 (pk로 가져옴)
        form = PostForm(request.POST, instance=post)
        if form.is_valid():
            post = form.save(commit=False)
            post.author = request.user
            post.published_date=timezone.now()
            #유효하면 그 instance에다가 다시 덮어씌워서 수정한다.
            post.save()
            return redirect('post_detail',pk=post.pk)
    #폼을 수정하려 한다면 저장된 해당 post 객체에서 원래 썼던 내용들을 다시 폼에 집어넣어준다(원래 있던 글을 수정하는거니까)
    else:
        form = PostForm(instance=post)
    return render(request, 'blog/post_edit.html', {'form' : form})

 

 

--------------------------------------------------------------------------

Django Girls Tutorial (https://tutorial.djangogirls.org/ko/) 사이트를 참조했습니다.

댓글