규도자 개발 블로그

django project에 contribute할 내용 (url dispatcher에 대한 건) 본문

Python/Django

django project에 contribute할 내용 (url dispatcher에 대한 건)

규도자 (gyudoza) 2019. 11. 18. 15:05

django project에 contribute할 내용 (url dispatcher에 대한 건)

예전에 관련 작업을 할 때마다 아 이건 django 프로젝트 커뮤니티에 제보를 하던가 혹은 내가 직접 contributor가 돼서 개선 혹은 변경을 해야겠다고 생각한 부분이다. 약 반년 전쯤에도 작업을 하다가 떠올랐던 부분인데 뭔지 까먹어서 잊었던 부분이고 최근에 또 작업하다가 big aha moment를 만나서 다시는 까먹지 않게 여기에나마 기록해두려 한다. 직접적인 개선 방법 및 커뮤니티에 기여자로 참여하는 방법들을 모르니 일단 여기에 기록해둔 뒤에 직접 기고할 계획으로 말이다.

 

이 생각이 든 건 form을 제공하는 페이지에서 데이터를 수정하고 저장할 때 url을 지정하는 부분을 작업할 때였다. 어떤 form이든 글을 새로 쓰나 수정하나 같은 form으로 제공해야하고 이에 맞춰서 url은 새로 쓸 땐 post/wirte형식으로 제공한다 하더라도 수정할 땐 post/wirte/3형식으로 pk를 함께 제공해야 했는데(방법의 차이는 있지만 가장 일반적인 형태에서) get request일땐 문제가 되지 않더라도 form의 action url을 지정하는 부분에 있어서 문제가 발생한다.

 일단 나는 지금 해당 부분을 다른 방식으로 커버하기 위해 일반 글쓰기에 해당하는 url만 추가해놓고 수정 중일 때는 form 의 action url 맨 뒤에 템플릿에서 post의 pk를 붙여서 억지로 url을 일치시키게 하는, 사실 굉장히 우스운 형태로 구현해놨다. <form action="{% url 'post_write' %}{{ post.id }}" method="post">이런 형식으로 말이다. 내가 원하는 건 <form action="{% url 'post_write' post.id %}" method="post">형식으로 url parameter안에 들어가도 수정과 새글쓰기 모두 커버할 수 있으며 만약에 post.id가 없으면 공백이 아닌, 그냥 없는 url route를 찾아들어가게 하는 기능이다.

 

예를 들어

urlpatterns = [
    path('post/write/', views.WritePost.as_view(), name='post_write'),
    path('post/write/<int:pk>', views.WritePost.as_view(), name='post_write'),
]

라는 url path를 추가했다 했을 때 작동이 제멋대로...라고 해야하나. 아무튼 내가 원하는 대로 작동하지 않는다. url name으로 제공하는 건 하나의 url이지만 새로운 글을 쓸 때와 글을 수정할 때 서로 다른 url을 제공해야 하는데 일단 get method를 실행시킬 때는 문제가 되지 않는다. 새글쓰기할 때는 원래 post.id가 없어서 url parameter에 추가하지 않았고 수정할 때는 애초에 post.id가 첨부되니 두 개의 루트 모두 따로따로 잘 작동한다.

 하지만 form url을 지정하는 부분에서 위에 썼다시피 새글쓰기때는 어차피 post.id가 없고 수정할 때는 post.id가 있으니 form action url도 똑같이 <form action="{% url 'post_write' post.id %}" method="post">이렇게 제공하면 되겠다! 싶었는데 아니나 다를까, 수정할 땐 문제가 되지 않지만 새글 쓸 땐 post.id가 없으나 parameter가 지정돼있어서 공백으로 처리되는데 위의 urlpatterns를 보면 알겠지만 첫번째 매개변수를 <int:pk>로 지정해놨기 때문에 오류가 발생한다. post.id가 없으면 위의 루트로 작동하고 post.id가 있으면 아래의 루트로 작동하면 참 좋을텐데 말이다. 여기서 깨달은 사실이 있다. django url dispatcher는 공백을 처리하지 못한다. 혹시나 해서 공백을 str로도 받아보려는 시도까지 해봤으나 무위로 돌아갔다.

 

 글을 쓰다가 개선사항이 생각나서 내 프로젝트에도 조금 수정을 가했다. 아예 urlpattern을 아래처럼 3개로 바꾸고

urlpatterns = [
    path('post/write/', views.WritePost.as_view(), name='post_write'),
    path('post/write/<int:pk>', views.WritePost.as_view(), name='post_write'),
    path('post/write/<str:action>', views.WritePost.as_view(), name='post_write'),
]

form 안의 url을 <form action="{% url 'post_write' post.id|default:'new' %}" method="post">로 바꾸고 같이 넘어오는 kwargs의 action이 'new'일 경우에는 새 게시물을 쓰고, 수정할 때는 post.id가 있으니 정상적으로 post.id가 url parameter에 들어가 아무 문제도 없었다. 글을 쓰다가 좀 더 개선된 해결책을 찾긴 했지만 그래도 한번 제안해보고 타당하다는 답변이 돌아오면 한번 기여도 해볼 생각이다.


결론은 이렇다.

현재의 django url dispatcher는 공백 parameter에 대한 처리가 안되니 이것을 조건문으로 구분하여 공백이 들어왔을 땐 아예 없는 것으로 처리하여 path에 연결하게 개선, 혹은 변경하고 싶다.

Comments