ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 장고 삭제 기능 구현
    백엔드 : 서버공부/Django 2023. 7. 29. 13:37
    728x90

    장고에서 삭제 기능을 구현해보겠습니다.

    동작하는 방식을 보자면

    글의 상세페이지를 눌렀을때 Delete버튼이 나타나게 됩니다.

    버튼을 클릭하면 해당 글이 삭제되고 홈으로 이동하도록 구성해보겠습니다.

     

    버튼을 추가해보겠습니다. 아래와 같은 코드를 추가해줍니다.

    <li>
       <form>
            <input type="submit" value="delete">
       </form>
    </li>
    

    아래는 수정사항이 반영된 HTMLTemplate함수입니다.

    def HTMLTemplate(articleTag):
        global topics
        ol = ''
        for topic in topics:
            ol += f'<li><a href="read/{topic["id"]}">{topic["title"]}</a></li>'
        return f'''
        <html>
        <body>
            <h1><a href="/myapp">Django</a></h1>
            <ol>
                {ol}
            </ol>
            {articleTag}
            <ul>
                <li><a href="/myapp/create/">create</a></li>
                <li>
                    <form>
                        <input type="submit" value="delete">
                    </form>
                </li>
            </ul>
        </body>
        </html>
       '''
    

     

    아래와 같이 버튼이 추가된것을 확인할 수 있습니다.

    delete의 기능을 구현해보겠습니다. 버튼을 링크로 구현할수도있습니다.

    기존의 코드인 <a href="/myapp/create/">create</a>이것처럼 작성하는 방법입니다.

    하지만 기본적으로 링크는 특정 페이지로 이동하는 것 입니다. 즉 GET방식을 통해 서버로 접속하는 것입니다. 때문에 delete버튼을 누를시 서버로이동하는 것이 아니라 서버의 데이터를 수정하는 방식으로 구현하려는 목적에 맞지 않습니다.

    서버의 정보를 수정하기 위해서 POST방식을 사용해야합니다.

    post는 form을 통해 만들기 때문에 form을 사용하여 코드를 수정해보겠습니다.

    def HTMLTemplate(articleTag, id=None):
        global topics
        contextUI = ''
        if id != None:
            contextUI = f'''
                <li>
                    <form>
                        <input type="submit" value="delete">
                    </form>
                </li>
            '''
        ol = ''
        for topic in topics:
            ol += f'<li><a href="read/{topic["id"]}">{topic["title"]}</a></li>'
        return f'''
        <html>
        <body>
            <h1><a href="/myapp">Django</a></h1>
            <ul>
                {ol}
            </ul>
            {articleTag}
            <ul>
                <li><a href="/myapp/create/">create</a></li>
                {contextUI}
            </ul>
        </body>
        </html>
       '''
    

    위와 같은 코드를 작성하면 화면상에 버튼이 추가됩니다. 이제 버튼을 클릭시에 이동할 경로를 지정해주겠습니다. 그러기 위해서 <form action="/myapp/delete/" method="post">과 같이 속성을 추가해줍니다.

     

    그 다음 서버에게 삭제하고싶은 글이 몇번인지 알려주어야 합니다. 이를 위해 read페이지template에 들어올때 두번째 인자로 id값을 전해주겠습니다.

    def read(request, id):
        global topics
        article = ''
        for topic in topics:
            if topic['id'] == int(id):
                article=f'<h2>{topic["title"]}</h2>{topic["body"]}'
        return HttpResponse(HTMLTemplate(article, id))
    

    id값을 받는 파라매터는 HTMLTemplate의 두번째 위치에서 받으면 되겠습니다.

    이때 read에서는 템플릿의 두번째 인자에 id값을 전달하지만 다른것은 그러지 않으므로 에러가 나게됩니다. 때문에 id=None 를 통해 id값이 없는 경우에는 none이라는 값을 전달해주겠습니다.

    def HTMLTemplate(articleTag, id=None):

    이제 id값을 서버로 전달해보겠습니다. input type=”hidden”이라는 방법을 사용하겠습니다. 이 방법은 눈에보이지는 않지만 데이터를 서버로 전송하면 데이터는 전송하는(?)방법입니다. 아래와같이 코드를 수정해줍니다.

    def HTMLTemplate(articleTag, id=None):
        global topics
        ol = ''
        for topic in topics:
            ol += f'<li><a href="read/{topic["id"]}">{topic["title"]}</a></li>'
        return f'''
        <html>
        <body>
            <h1><a href="/myapp">Django</a></h1>
            <ul>
                {ol}
            </ul>
            {articleTag}
            <ul>
                <li><a href="/myapp/create/">create</a></li>
                {contextUI}
            </ul>
        </body>
        </html>
       '''
    

    위와같이 코드를 작성하면 정상적으로 서버에 id값이 전달됩니다.

     

    전송하는 부분은 구현이 되었으므로 서버를 받는 부분을 구현해보겠습니다.

    myapp에 있는 urls.py를 열어서 수정합니다. 아래는 기존의 코드입니다.

    """myproject URL Configuration
    The `urlpatterns` list routes URLs to views. For more information please see:
        <https://docs.djangoproject.com/en/3.2/topics/http/urls/>
    Examples:
    Function views
        1. Add an import:  from my_app import views
        2. Add a URL to urlpatterns:  path('', views.home, name='home')
    Class-based views
        1. Add an import:  from other_app.views import Home
        2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
    Including another URLconf
        1. Import the include() function: from django.urls import include, path
        2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
    """
    
    from django.urls import path
    from myapp import views
    urlpatterns = [
        path('', views.index),
        path('create/', views.create),
        path('read//', views.read)
    ]
    

    해당 코드에 path를 추가해보겠습니다.

    """myproject URL Configuration
    The `urlpatterns` list routes URLs to views. For more information please see:
        <https://docs.djangoproject.com/en/3.2/topics/http/urls/>
    Examples:
    Function views
        1. Add an import:  from my_app import views
        2. Add a URL to urlpatterns:  path('', views.home, name='home')
    Class-based views
        1. Add an import:  from other_app.views import Home
        2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
    Including another URLconf
        1. Import the include() function: from django.urls import include, path
        2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
    """
    
    from django.urls import path
    from myapp import views
    urlpatterns = [
        path('', views.index),
        path('create/', views.create),
        path('read//', views.read),
        path('delete/',views.delete)
    ]
    

     

    다시 views.py로 돌아와 delete함수를 구현해보겠습니다.

    @csrf_exempt
    def delete(request):
        global topics
        if request.method == 'POST':
            id = request.POST['id']
            newTopics = []
            for topic in topics:
                if topic['id'] != int(id):
                    newTopics.append(topic)
            topics = newTopics
            return redirect('/myapp/')
    

    먼저 서버로 전송된 데이터가 POST방식으로 전송된 것인지 확인해야합니다. 그 다음으로는 id값을 알아내야합니다. 이를 위해서 global topics를 선언하고 newTopics = []라는 새로운 비어있는 리스트를 만듭니다. 그 다음 for문을 통해 순회하면서 id와 일치하지않는 topic들을 newTopics에 추가하겠습니다.

    그리고 topics = newTopics를 통해 newTopicstopics로 바꿉니다.

    그 다음 return redirect('/myapp/')를 통해 사용자를 홈으로 보냅니다.

     

    페이지를 로드해서 삭제기능이 잘 작동하는지 확인해보겠습니다.

    먼저 페이지에서 routing을 클릭하면 상세페이지에 삭제버튼이 나타나있는 것을 확인할 수있습니다.

    위와같이 삭제버튼을 누르게되면 해당 글은 삭제가 되고, 홈화면으로 이동한 것을 확인할 수 있습니다.

     

    페이지의 완성도를 위해 홈화면에서는 삭제버튼이 나타나지않고 상세페이지에서만 나타나게해보겠습니다.

    현재 템플릿안에서는 id값이 있는가 없는가에 따라서 상세페이지인가 아닌가를 판단할 수 있습니다. 따라서 조건문을 통해 id가 있을때만 조건문이 나오도록 하겠습니다.

     

    먼저 맥락에따라 ui가 만들어지도록한다는 의미에서 contextUI라는 변수를 만들겠습니다.

    이 변수는 id가 None이 아닐때 정의하겠습니다.

    def HTMLTemplate(articleTag, id=None):
        global topics
        contextUI = ''
        if id != None:
            contextUI = f'''
                <li>
                    <form action="/myapp/delete/" method="post">
                        <input type="hidden" name="id" value={id}>
                        <input type="submit" value="delete">
                    </form>
                </li>
            '''
        ol = ''
        for topic in topics:
            ol += f'<li><a href="read/{topic["id"]}">{topic["title"]}</a></li>'
        return f'''
        <html>
        <body>
            <h1><a href="/myapp">Django</a></h1>
            <ul>
                {ol}
            </ul>
            {articleTag}
            <ul>
                <li><a href="/myapp/create/">create</a></li>
                {contextUI}
            </ul>
        </body>
        </html>
       '''
    

    페이지를 보면 홈화면에서는 delete버튼이 없지만 상세보기에선 버튼이 나타나는것을 확인할 수 있습니다.

    홈 화면
    상세 페이지

    장고의 삭제 기능을 완성했습니다.

     

    '백엔드 : 서버공부 > Django' 카테고리의 다른 글

    장고 앞으로 공부할 것들  (0) 2023.08.07
    장고 수정 기능 구현  (0) 2023.07.31
    장고 생성 기능 구현 2  (0) 2023.07.29
    장고 생성 기능 구현 1  (0) 2023.07.29
    장고 읽기 구현 2  (0) 2023.07.29
Designed by Tistory.