📌 복습!!
Django는 브라우저에서 클라이언트(사용자) 가 요청 을 보내면, 해당 요청 주소 와 일치하는 기능(view) 을 파악하여 기능을 수행 하고 요청에 맞는 응답 을 주는 흐름을 가지고 있다.
일반적이 화면의 이동만 하는 요청의 경우에는 요청 주소에 특정한 값을 전달할 필요가 없다.
하지만 데이터 생성, 수정, 삭제
등과 같이 특정 기능을 필요로 하는 요청을 보내면 기능을 수행하기위한 파라미터(변수)
가 필요하다.
이를 클라이언트(사용자)가 전달해 줄 수 있는데 그 파라미터(변수)를 전달하는 방법을 알아보려고 한다.
# 📌 urls.py
urlpatterns = [
path('', index_view, name='index'),
]
# 📌 views.py
def index_view(request):
user = Users.objects.filter(username='admin').first()
email = user.email if user else "Anonymous User!"
return render(request, "index.html", {"welcome_msg" : f"Hello {email}!", "hello" : "World"})
위 함수는 주소 창에 아래의 주소로 함수가 처리하여 index.html페이지로 이동을 한다.
http://127.0.0.1:8000/shortener/
하지만 이때 우리는 url 주소만 입력했지 특정 값
이나 파라미터(요소)
등을 전달한 적이 없다.
이제 파라미터가 포함한 요청을 보내 함수가 어떻게 파라미터를 받을 수 있는지
살펴보자.
첫 번째로 값을 전달하는 방법에는 path 파라미터가 있다.
path 파라미터란? 요청 url 주소에 포함된 하나의 변수
이다.
http://127.0.0.1:8000/shortener/user/1
GET
위의 요청 주소에는 HTTP GET method로 user의 값이 1 인 데이터를 요청함
과 같은 의미를 가진다.
이러한 path 파라미터는 아래와 같은 특징을 가지는데
특징
변수
를 담는다.엔드포인트의 일부
이다.하나의 데이터에 대한 정보
를 받아올때 적절하다.이제 Django에서 path 파라미터가 담긴 url을 어떻게 작성하면 좋을까?
📌 urls.py
urlpatterns = [
# 파라미터 미포함
path('shortener', index_view, name='index'),
# path 파라미터가 포함
# shortener/user/1/
path('user/<int:user_id>', get_user),
]
전달하려는 파라미터가 없다면 위와 같이, 반대로 전달하려는 파라미터를 주소에 담고 싶다면 아래와 같이 사용하면 된다.
/shortener/user/1/에서 1
이 <int:user_id>
가 부분이다.
🗣 int형 데이터를 user_id 변수에 담아 보내라!!
라고 생각하면 되겠다.
이렇게 작성한 url 주소의 path 파라미터를 view의 함수가 어떻게 받을까?
# 📌 urls.py
urlpatterns = [
path('user/<int:user_id>', get_user),
]
# 📌 views.py
def get_user(request, user_id):
...
user = Users.objects.filter(pk=user_id).first()
...
return render(request, "base.html", {"user" : user, "params" : [abc, xyz]})
url 주소를 user/<int:user_id>
로 user_id
라는 파라미터를 보냈다.
그렇다면 해당하는 url 주소를 받는 함수 get_user()는 파라미터로 동일한 user_id
를 받아야만한다.
그래서 함수 get_user()함수에 request
와 user_id
를 파라미터로 받아 코드를 작성했다.
이렇게 받은 user_id는 하나의 변수로 사용이 되면 ORM을 통해 데이터를 조회하거나 데이터 처리 등에 사용이 된다.(CRUD)
요청 주소에 파라미터를 담는 방법이 하나 더 존재한다.
이 방법은 query string이라 부르며 query 파라미터라고도 한다.
http://127.0.0.1:8000/shortener/user/1?abc=ABC&xyz=XYZ
GET
위의 요청 주소에는 path 파라미터인 HTTP GET method로 user의 값이 1 인 데이터를 요청함
의 의미와 추가적인 abc값이 ABC이며 xyz값이 XYZ이다.
라는 조건이 추가가 되었다.
이것을 바로 query string이라 부르는데 아래와 같은 특징을 가진다.
특징
shortener/user/1?abc=ABC&xyz=XYZ
filtering
, sorting
, searching
에 적절하다.그럼 Django에서 query string 담긴 url을 어떻게 작성하면 좋을까?
query string은 path 파라미터와 다르게 url에서는 특별히 작성하지 않는다.
query string은 middle ware가 넘겨주는 request
에 담겨 넘어오기 때문이다.
query string을 view의 함수가 어떻게 받을까?
def get_user(request, user_id):
...
abc = request.GET.get("abc")
xyz = request.GET.get("xyz")
user = Users.objects.filter(pk=user_id).first()
return render(request, "base.html", {"user" : user, "params" : [abc, xyz]})
위에서 query string은 request변수
에 담겨 온다고 했다.
view에서 함수는 urls.py를 거쳐 views.py로 넘어 올때 몇개의 middle ware
를 거치는데, 이때 request변수에 query string의 변수와 값도 함께 넘어 온다.
view의 함수는 반드시 request를 파라미터로 받아야 하기 때문에 query string으로 넘어온 값을 사용할 수 있다.
request.GET.get("abc")
로 abc 키값을 가진 query string을 받았다.
🗣 이는 request의 GET(HTTP method)안에 "abc"값을 가져와!
라는 뜻으로 생각하면 된다.
📌 views.py
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def get_user(request, user_id):
...
abc = request.GET.get("abc")
xyz = request.GET.get("xyz")
user = Users.objects.filter(pk=user_id).first()
return render(request, "base.html", {"user" : user, "params" : [abc, xyz]})
위와 같이 path 파라미터를 이용해 Users객체
와 query string을 이용해 abc
, xyz
값을 render()함수의 context에 전달하였다.
이렇게 전달한 context를 어떻게 html문서에서 이용할 수 있을까 알아보자.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Base Page</title>
</head>
<body>
{{ user }} <br>
{{ user.email }}<br>
{% for i in params %}
{{ i }}<br>
{% endfor %}
{% if user.email == "admin@shortener.com" %}
<h1>{{ user }}는 할 수 있다.</h1>
{% else %}
<h1>{{ user }}는 할 수 없다.</h1>
{% endif%}
</body>
</html>
{{ user }}
, {{ user.email }}
과 같이 템플릿 변수
로 또는 {% for i in params %}
와 같은 템플릿 태그
를 이용하여 python문법을 html문서에서 사용할 수 있다.view에서
user라는 객체
를 통체로 보냈기 때문에 user객체 안에 있는 email도 사용이 가능하다.템플릿 필터
도 존재하지만 자세한 내용은 다음에 다루도록 하겠다.현재까지는 url요청을 브라우저의 주소창에 url 주소를 입력하여 요청을 보내는 방식을 사용하였다.
웹 개발을 하면서 브라우저를 열어 url을 입력하는 것도 방법이긴 하지만, Backend 개발자에게 브라우저를 열고 이벤트 UI/UX를 클릭하고 클릭한 요청을 기다리는 것이 오래걸리고 매번 그 과정을 반복하는 것은 번거롭다.
그래서 브라우저의 변화는 보지 않고 요청을 보내면 결과 값만을 확인할 수 있는 POSTMAN을 사용해 보려고 한다.
POSTMAN 은 API 개발 방식에 사용되며, API개발자에게 필수적인 프로그램이다.
📌 views.py
@csrf_exempt # csrf 예외 처리
def get_user(request, user_id):
if request.method == 'GET':
abc = request.GET.get("abc")
xyz = request.GET.get("xyz")
user = Users.objects.filter(pk=user_id).first()
return render(request, "base.html", {"user" : user, "params" : [abc, xyz]})
elif request.method == 'POST':
username = request.GET.get("username")
if username:
user = Users.objects.filter(pk=user_id).update(username=username)
return JsonResponse(status=201,data=dict(msg="You just reached with Post Method!"), safe=False)
위의 코드에 HTTP mehtod를 if문을 통해 분기를 걸었다.
HTTP method가 뭔데?
HTTP method는 API 요청(브라우저의 url요청, 이벤트 버튼의 api 등)에서 요청 방식을 정하는 변수이다.
HTTP method는 GET, POST, DELETE, FETCH 등이 존재하며 자세한 내용은 다른 글에서 상세히 알아보고, 코드로 작성한 GET, POST만 다뤄보려고 한다.
request.method == 'GET'
일반적으로 브라우저 주소창에 입력해 화면이동하는 것은 HTTP method가 GET에 해당한다.
request.method == 'POST'
일반적인 사이트에서 버튼을 클릭하여 저장처리를 하는 요청이 HTTP method가 POST에 해당한다.
그래서 왜 나눈건데?
코드에서 GET과 POST를 나눈 이유는 view에서 HTTP method가 무엇이냐에 따라 어떻게 처리를 하는지 그리고 어떤 처리에 HTTP method를 설명하려고 한다.
request.method == 'GET'
에는 abc, xyz, user를 context에 담아 화면이동이 구현되어 있다.
abc = request.GET.get("abc")
xyz = request.GET.get("xyz")
user = Users.objects.filter(pk=user_id).first()
return render(request, "base.html", {"user" : user, "params" : [abc, xyz]})
request.method == 'POST'
에는 query string 'username'을 받아 user객체의 username값을 변경하는 로직이 구현되어 있다.
elif request.method == 'POST':
username = request.GET.get("username")
if username:
user = Users.objects.filter(pk=user_id).update(username=username)
return JsonResponse(status=201,data=dict(msg="You just reached with Post Method!"), safe=False)
먼저 브라우저에서 주소창에 url을 입력하면 GET 방식의 화면이동이기 때문에 화면이 이동하며 html에 아래와 같이 나오는 것을 볼 수 있다.
하지만 POST 방식은 저장을 버튼이나 특정 이벤트를 화면에서 구현하지 않는 이상 바로 확인이 불가능 하다.
그래서 우리는 POSTMAN 을 사용하는 것이다.
이렇게 요청을 성공한 후 다시 브라우저에서 동일한 주소를 입력하여 화면을 확인해 보자.
username이 변한 결과를 확인할 수 있을 것이다.