Django #6 | Django_tutorial(part#3)

신승호·2021년 4월 22일
0

Django

목록 보기
6/7

URL view template 이 어떻게 연결되는 지 보자악 !

4개의 view 를 만들어 보자.

  • 질문 《색인》 페이지 – 최근의 질문들을 표시합니다.
  • 질문 《세부》 페이지 – 질문 내용과, 투표할 수 있는 서식을 표시합니다.
  • 질문 《결과》 페이지 – 특정 질문에 대한 결과를 표시합니다
  • 투표 기능 – 특정 질문에 대해 특정 선택을 할 수 있는 투표 기능을 제공합니다.

먼저 이것만 기억해보자

view에서는 request라는 인수를 받고, HttpRespose를 return 한다

  • "request에는 여러가지 정보들이 담겨 있을 것이고 다시 response 해줄것이다" 이게 다임
  • 긍까, return전까지 여러가지 작업을 추가해놓은다음 그 값을 return 하겠다는 말이지 ㅋㅎ ^_^

view에 새로운 기능 추가하기

  • polls/views.py세부(detail), 결과(result), 투표(vote) 기능 추가
from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, world.")

def detail(request, question_id):
    return HttpResponse("You're looking at question %s." % question_id)	# HttpResponse return 하지 ?

def results(request, question_id):
    response = "You're looking at the results of question %s."
    return HttpResponse(response % question_id)	 			# HttpResponse return 하지 ?

def vote(request, question_id):
    return HttpResponse("You're voting on question %s." % question_id)	# HttpResponse return 하지 ?

새롭게 추가한 기능을view를 호출하기 위해 urls.py코드 재 작성

  • polls/urls.py에서 고고
from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),    				# ex: /polls/
    path('<int:question_id>/', views.detail, name='detail'),		# ex: /polls/5/
    path('<int:question_id>/results/', views.results, name='results'),  # ex: /polls/5/results/
    path('<int:question_id>/vote/', views.vote, name='vote'),		# ex: /polls/5/vote/
]

새로운 기능을 가진 views.pyurls.py를 연결 시켰다 ! !

  • 이제 뭘 해보자.. !

뭔가 실제로 뭘 하기 만들기

  • 각 View는 HttpResponse 객체를 반환하거나, 혹은 Http404 같은 예외를 발생하게 해야합니다..
  • 할튼 이 두가지중 하나는 무조건 return 된다.

현재 view에서 request에서 question("what's up")을 출력하도록 해보자

  • 종전 view에서 request는 그 hellow, world만 출력하도록 되어있었다.
  • 코드를 수정해서 question을 출력하도록 해보장
    • 수정을 한다음에 출력을 해보면 "What's up"이 출력된다 ! !! !
    • 근데 왜 어떻게 index(request)가 이거를 출력하는지는.. 잘 모르겠다....
from django.http import HttpResponse
from django.template import loader

from .models import Question						# 이자식 추가하고 ㅡ ㅡ

# Create your views here.
def index(request):
    # return HttpResponse("Hello, world.")	# 전 출력 내용 요건 추가 ㄴㄴ
    latest_question_list = Question.objects.order_by('-pub_date')[:5]	#퀘스쳔 데이트중, 출판일자를 정렬하여 5개까지만 가지고와라
    output = ', '.join([q.question_text for q in latest_question_list]) # 이 5개를 콤마로 연결해서 스트링으로(문자열)만들게되고 이걸 출력 
    return HttpResponse(output)

# 아래는 그대로 두자악 ! 

def detail(request, question_id):
    return HttpResponse("You're looking at question %s." % question_id)

def results(request, question_id):
    response = "You're looking at the results of question %s."
    return HttpResponse(response % question_id)

def vote(request, question_id):
    return HttpResponse("You're voting on question %s." % question_id)
  • 지름길있다 ㅡ ㅡ 바로바로 rander() 쓰는거
from django.shortcuts import render

from .models import Question


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    output = ', '.join([q.question_text for q in latest_question_list])
    return HttpResponse(output)

def detail(request, question_id):
    return HttpResponse("You're looking at question %s." % question_id)

def results(request, question_id):
    response = "You're looking at the results of question %s."
    return HttpResponse(response % question_id)

def vote(request, question_id):
    return HttpResponse("You're voting on question %s." % question_id)

어떻게 하면 수정 영향범위 를 줄일 수 있을 까 .. 고민해야한다 .. !?

  • 클라이언트에게 보여주는걸 목적으로 그냥 막 작성한 polls/views.py안에있는 python 코드를 그대로 가지고 프론트 앤드가 디자인을 수정하기엔 좀 마니 어려워 쏘 복잡띠,,,
    • views.py안에있는 python 코드들에 디자인을 위한 코드들이 같이있다 ㅡ ㅡ
      • 페이지가 보여지는 방식을 바꿀라면 ? python 코드 다바꿔야지 ;;;;

    그니까, views.py에서 사용할 수 있는 templates을 만들어서 따로 작성해서, python 코드와 / 디자인을 위한 코드를 분리해보자

내부 로직 담당인 view 와 디자인 담당인 Template 분리하자

  • views.py안에 index 뷰를 업데이트 하면서context 라는 새로운 변수를 넣었을 때 , polls/detail.html이라는 템플릿을 어떻게 받아오는지 보자
  • 먼저, polls/templates/polls 안에 index.html을 만들고 아래 내용을 넣자
<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>
  • Templates 이용하여 polls/views.pyindex를 업데이트 한다.
    • Templates을 하는데 왜때문에 views.py를 고치냐 ?
      • urls.py -> views.py -> models.py -> views.py -> templates 를 하는중임 ㅋㅎ
from django.shortcuts import render
from django.http import HttpResponse
from django.template import loader			# 이자식이 추가되었고

from .models import Question

# Create your views here.
def index(request):
    #return HttpResponse("Hello, world")
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    template = loader.get_template('polls/index.html')			# "polls/index.html" templates를 불러와서 가장 첫줄을 받는다
    context = {								# 그런후 context로 전달한다. / context는 템플릿에서 쓰이는 변수명과 Python 객체를 연결하는 사전형 값이다.
        'latest_question_list': latest_question_list,
    }
    return HttpResponse(template.render(context,request))
  • what's new? 이게 나올 것이야 / 나는 내가 what's new? 로 바꿈 ㅋㅎ

위 코드와 동일하고 좀 짧은 지름길이 있다

  • index 뷰를 단축 기능으로 작성해볼궤 ! render()사용
# polls/views.py	
from django.shortcuts import render
`
from .models import Question
`
`
def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {'latest_question_list': latest_question_list}
    return render(request, 'polls/index.html', context)			# render()은 1. request를 받고/ 2. template 이름을 받고, 3. context(이건 옵셔널임 -> 근데 결국 인수로 지정된 context로 표현된 템플릿의 HttpResponse 객체가 반환)
  • 모든 뷰에 적용한다면, loader와 HttpResponse를 import 안해도돼
  • 근데 class detail, results, vote에서 stub 메소드를 가지고 있다면, HttpResponse import유지해야해 ㅡ ㅡ
    • 근데 stub 메소드 뭐야 ?

404 에러 일으키기

  • polls/views.py에서 excetp문 추가 시키자~~
from django.http import Http404
from django.shortcuts import render

from .models import Question


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {'latest_question_list': latest_question_list}
    return render(request, 'polls/index.html', context)

def detail(request, question_id):
    try:
        question = Question.objects.get(pk=question_id)			# 2. question_id를 pk로 받고 Question을 조회를 했을때 데이터가 없으면
    except Question.DoesNotExist:					# 1. question에 데이터가 없는경우
        raise Http404("Question does not exist")			# 3. 이게 보여질 것이다! 
    return render(request, 'polls/detail.html', {'question': question})
 
def results(request, question_id):
    response = "You're looking at the results of question %s."
    return HttpResponse(response % question_id)

def vote(request, question_id):
    return HttpResponse("You're voting on question %s." % question_id)
  • polls/templates/polls/detail.html 또한 같이 수정 ! !
{{ question }}
  • 지름길이 또 이써 ^^
    • get_object_or_404() 사용
from django.http import HttpResponse, Http404
from django.template import loader
from django.shortcuts import get_object_or_404, render			# 추가 했지 ?
`
from .models import Question
`
def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {
        'latest_question_list': latest_question_list,
        }
    return render(request, 'polls/index.html', context)
`
def detail(request, question_id):					# 추가 했지 여겨도 
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/detail.html', {'question': question})
`
def results(request, question_id):
    response = "You're looking at the results of question %s."
    return HttpResponse(response % question_id)
`
def vote(request, question_id):
    return HttpResponse("You're voting on question %s." % question_id)

Template시스템 이용하기

  • 먼저, polls/templates/polls/detail.html 함보고 코드 추가하자
<h1>{{ question.question_text }}</h1>		# Django는 먼저 question 객체에 대해 사전형으로 탐색
<ul>
{% for choice in question.choice_set.all %}	# 메소드 호출  question.choice_set.all =  question.choice_set.all()처럼 사용됨
    <li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>

template에서 하드코딩된 URL 제거하자

  • polls/index.html template에 링크를 넣으면, 이 링크는 부분적으로 하드코딩된다 . !
{% if latest_question_list %}
    <ul>
    {% for question in latest_question_list %}
        <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>  # 이부분 하드코딩 될꺼야 ! !!
    {% endfor %}
    </ul>
{% else %}
    <p>No polls are available.</p>
{% endif %}
  • polls.urls 모듈의 path() 함수에서 인수의 이름을 정의했으므로, {% url %} template 태그를 사용해서 url 설정에 정의된 특정한 URL 경로들의 의존성을 제거할 수 있다. ?? ?뭔말인지 나도 몰겠음
    • {% url %} template 태그를 사용해서 url경로 의존성을 제거 할 수 있다 ! 라고 기억이나 하자
  • 그래서, {% url %} 이걸 써서 바꿔보자
{% if latest_question_list %}
    <ul>
    {% for question in latest_question_list %}
        <li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li> 	# 바뀐 부분 이 여기다
    {% endfor %}
    </ul>
{% else %}
    <p>No polls are available.</p>
{% endif %}
  • 위 의 코드가 polls.urls 모듈에 있는 URL을 탐색하는 한다고 생각해
  • detail.pyURL이 어떻게 되어있길래 위 코드로 탐색한다는 겨
path('<int:question_id>/', views.detail, name='detail'), # 이 줄의 'name'과 template tag의 {% url %} 과 같다고 생각해
  • 여기서 URLpolls/specifics/12/로 바꾸고 싶다면, polls/urls.py에서 바꿔라
path('specifics/<int:question_id>/', views.detail, name='detail'),	# 앞에 specifics를 추가해주면 깰끔

URL 이름 정해보자

  • 실제 프로젝트에는 app이 여러개 올꺼야, 그럼 이 모든 app의 url을 어떻게 구별 하지 ?
    • 이름을 붙혀주자 !! 어디다가 이름을 붙혀줄 수 있지 ?
    • app 의 urls.py 에 다가 이름을 넣어주면 돼 !
      • polls/urls.py로 가자
from django.urls import path

from . import views

app_name = 'polls'			# 이렇게 이름을 요기다가 지어주면 딱 좋아
urlpatterns = [
    path('', views.index, name='index'),
    path('<int:question_id>/', views.detail, name='detail'),
    path('<int:question_id>/results/', views.results, name='results'),
    path('<int:question_id>/vote/', views.vote, name='vote'),
]
  • 위처럼 바꿔주면 polls/templates/polls/index.html 에서도 detail 앞에 이름 딱 써주면 좋아
<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>

오늘은 여기까지 ㅡ ㅡ

profile
신승홉니다

0개의 댓글