동적 URL이란 웹페이지의 내용이, 서버가 제공하는 매개변수에 따라 바뀌는 URL이다. 간단하게 생각하면 www.example.com/user/1 에서 1번 유저의 정보를 불러오고 숫자를 바꾸면 각 번호에 해당되는 유저의 정보를 불러오는 식이다.
장고에서 동적인 URL을 만들기 위해서는 urls.py의 path에 각괄호(<>)를 사용한다. 괄호 안에는 view에서 불러올 변수의 타입:변수명을 넣어준다.
# views.py
# 함수 안에 인자로, 불러올 변수명을 넣어주어야 한다.
def updateOrder(request,pk):
order=Order.objects.get(id=pk)
form=OrderForm(instance=order)
if request.method == "POST":
#print('printing post:', request.POST)
form=OrderForm(request.POST, instance=order)
if form.is_valid():
form.save()
return redirect('/')
context={'form':form}
return render(request, 'accounts/order_form.html', context)
# urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name="home"),
....
path('update_order/<str:pk>', views.updateOrder, name="update_order"),
기능을 추가하면서 처음에 정했던 url이 변경되는 경우가 있다. url을 변경할 때마다 html의 href를 바꿔야 한다면 엄청난 시간낭비일 것이다. 이를 방지하기 위해 url패턴에는 name을 설정할 수 있다.
# urls.py
urlpatterns = [
path('', views.home, name="home"),
path('products/', views.products, name="products"),
path('customer/<str:pk>/', views.customer, name="customer"),
위와 같이 path의 키워드 인자로 name을 주면 실제 주소가 products에서 goods로 바뀌더라도 name은 그대로이므로 html은 수정하지 않아도 바뀐 url로 이동하게 된다.
html에서 name을 사용하기 위해서는 템플릿 태그를 사용하여 href="{% url 'name' [변수명.객체명] %}"
과 같이 작성한다. 여기서 [변수명.객체명]은 옵션으로, url이 불러오는 view함수에서 만든 변수와 그 객체를 가져올 때 사용한다. 예를 들어 동적 URL에서 고객 id와 같은 객체를 가져오고 싶을 때 사용한다.
정보를 입력받아 데이터를 생성하기 위해서는 폼이 필요하다. 그러므로 forms.py를 생성하여 from django.forms import ModelForm
장고의 내장 폼을 import한다. 그리고 폼에 작성한 데이터를 데이터베이스에 저장하기 위해 from .models import 모델명
으로 데이터를 저장할 모델을 import한다.
from django.forms import ModelForm
from .models import Order
# OrderForm클래스는 ModelForm 클래스를 상속
class OrderForm(ModelForm):
class Meta:
# 모델은 models.py의 Order 모델을 사용
model=Order
# 필요한 필드만 가져올 때는 [필드명, 필드명]
fields='__all__' # 모든 필드
폼을 작성했으면 폼에서 동작할 함수(view)를 만들어야 한다. 아래의 함수를 보며 확인하고자 한다.
def createOrder(request):
form=OrderForm()
if request.method == "POST":
form=OrderForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
context={'form':form}
return render(request, 'accounts/order_form.html', context)
forms.py에서 만든 폼 클래스를 form변수에 할당한다. 폼이 작성되고 저장 요청(request.method=="POST"
)이 들어오면, 작성한 내용을 폼에 넣는다.->OrderForm(request.POST)
내용이 유효한지 확인(if form.is_valid()
)하고 문제가 없다면 저장(form.save()
)한다. 저장한 후에는 루트디렉터리로 이동(return redirect('/')
)한다.
내용이 입력되지 않았다면(처음 create 했을 때) 입력 폼 화면으로 이동한다.(return render(request, 'accounts/order_form.html', context)
)
html에서 폼을 불러올 때는 <form> 시작 태그 밑에 {% csrf_token %}을 넣고 그 밑에 {{form}}을 넣는다.
데이터베이스에 저장된 데이터를 수정할 때는 create와 약간의 차이가 있다. 이미 입력된 내용을 불러와서 수정하는 것이기 때문에 폼을 요청했을 때 폼에는 전에 입력했던 내용이 들어 있어야 한다.
from django.forms import ModelForm
from .models import Order
# 저장된 폼을 찾아야 하기 때문에 id로 찾기 위해 pk인자를 넣는다.
def updateOrder(request,pk):
order=Order.objects.get(id=pk)
# 폼을 불러올 때 입력했던 내용을 포함시켜서 불러오려면 폼에 instance=order를 넣어준다.
form=OrderForm(instance=order)
if request.method == "POST":
# 수정한 내용으로 저장하기 위해 다시 instance=order를 넣어준다.
form=OrderForm(request.POST, instance=order)
if form.is_valid():
form.save()
return redirect('/')
context={'form':form}
return render(request, 'accounts/order_form.html', context)
# 삭제할 데이터를 찾기 위해 id를 인자로 찾는다
def deleteOrder(request, pk):
# 삭제할 객체 탐색
order=Order.objects.get(id=pk)
if request.method=="POST":
# POST로 삭제 요청이 왔으면 delete()로 삭제
order.delete()
return redirect('/')
context={'item':order}
return render(request, 'accounts/delete.html', context)