Django 프로젝트 3주차 - form action

Red_Panda·2021년 8월 13일
0

Python & Django

목록 보기
6/7

이번주는 많은 것을 하지 않았는데도 막히는 부분을 만났다.

이번에 나를 고생시킨 것은 바로 form의 action이다.

목표 기능 : 레시피를 등록한 사람이 자신의 글을 수정, 삭제할 수 있는 기능

삭제 기능은 비교적 쉽게 구현할 수 있었다.

view.py

@login_required(login_url='common:login')
def recipe_delete(request, recipe_id):
    recipe = get_object_or_404(Recipe, pk=recipe_id)
    if request.user != recipe.writer:
        messages(request, "삭제권한 없음")
        return redirect('naengpa:detail', recipe_id = recipe.id) # 원래 글로 돌아오기
    recipe.delete() # 해당 글 삭제
    return redirect('naengpa:index') # 삭제시 메인 화면으로
recipe_detail.html

<a href="#" class="delete btn btn-sm btn-outline-secondary" style="width : 70px; height:30px; margin-right:20px;"
                    data-uri="{% url 'naengpa:recipe_delete' recipe.id %}">삭제</a>
                    
<script type="text/javascript">
    $(document).ready(function(){
    $('.delete').on('click', function() {
        if(confirm("삭제를 진행하시겠습니까?")) {
            location.href = $(this).data('uri');
        }
    });
});
</script>
                    
urls.py

urlpatterns = [ 
path('recipe/delete/<int:recipe_id>/', views.recipe_delete, name="recipe_delete"), # 추가
]


html에서 내용밑에 삭제 버튼을 만들어주고 JQuery로 data-uri를 받아오고, 삭제할 것인지 확인창을 띄운다.
확인을 누르면 data-uri인 {% url 'naengpa:recipe_delete' recipe.id %} 가 호출이 되면서 삭제가 진행된다.

다음으로는 수정 기능을 만들었다.

views.py

@login_required(login_url='common:login')
def recipe_modify(request, recipe_id): # 레시피 수정
    recipe = get_object_or_404(Recipe, pk=recipe_id)
    
    if request.user != recipe.writer:
        messages.error(request, '수정권한이 없습니다.')
        return redirect('naengpa:detail',recipe_id = recipe.id)

    if request.method == "POST": # 수정완료 버튼 ( 레시피 등록하기 버튼)
        form = RecipeForm(request.POST, request.FILES, instance=recipe)
        if form.is_valid():
            recipe = form.save(commit=False)
            recipe.modify_date = timezone.now()
            recipe.save()
            return redirect('naengpa:detail', recipe_id = recipe.id) # 수정완료시 해당 글 detail로

    else: # method == GET
        form = RecipeForm(instance=recipe) # 해당글의 원래 정보도 같이 불러온다.

    context = {'form': form}
    return render(request, 'naengpa/recipe_create_form.html',context)
    
@login_required(login_url='common:login')
def recipe_create(request):
    if request.method == 'POST':
        form = RecipeForm(request.POST, request.FILES)
        # 이미지 등 파일 업로드시에는 request.FILES 추가 해야함!!
        if form.is_valid():
            recipe = form.save(commit=False)
            recipe.writer = request.user
            recipe.create_date = timezone.now()
            recipe.save()
            return redirect('naengpa:index')
    else: # 레시피 등록하기 GET방식 <a href=>링크 통한 요청은 GET
        form = RecipeForm()
    context = {'form':form}
    return render(request,'naengpa/recipe_create_form.html', context)
urls.py

path('recipe/modify/<int:recipe_id>/', views.recipe_modify, name="recipe_modify")
recipe_detail.html

<a href="{% url 'naengpa:recipe_modify' recipe.id  %}"
                        class="btn btn-sm btn-outline-secondary" style="width:70px; height:30px; margin-right:20px; " >수정</a>

수정기능의 경우 2가지 요청으로 나뉜다.

수정 버튼을 누르는경우 페이지를 요청하기 때문에 GET 요청이 발생한다. 그래서 GET 요청이 발생하는 경우 기존에 레시피를 등록할때 쓰던 form인 ReciperForm을 불러오는데, instance=recipe를 이용해 기존 정보도 함께 가져온다. (여기서 recipe는 recipe = get_object_or_404(Recipe, pk=recipe_id)다.)

recipe_create_form.html # 등록, 수정 form 화면

<form method="post" enctype="multipart/form-data" class="post-form" action="{% url 'naengpa:recipe_create' %}">


다음으로 불러온값을 수정하여 수정완료(레시피 저장하기)버튼을 누르면 위 코드에 의해 POST요청이 발생한다.

수정할때 사진을 변경하지 않는다면 기존사진 값이 있기때문에 null=False를 만족하여 저장되어야한다. 그런데 자꾸 사진은 반드시 넣어야한다는 field 오류가 났다.
내용들은 잘 가져왔기때문에 instance를 이용할때는 사진(파일)을 제대로 가져오지 않는지 확인했다. 참고로, 위 사진은 작업을 모두 완료한 후라 사진이 잘 보인다.


요소를 확인했더니 value값을 잘 가지고 오는것을 확인했다.

어떤것이 문제인지 다시 찾기위해 수정하는 작업을 이리저리 반복하는 도중에 새로운 문제점을 발견할 수 있었다. 바로 레시피 저장하기 버튼을 누르는순간 cmd에서 recipe_create가 발생하는것을 발견했다!
recipe_modify가 발생해야하는데 말이다. 그래서 이 부분에 대해서 조사했다.

그 결과 form에서 지정한 action="{% url 'naengpa:recipe_create' %}"이 문제임을 알 수 있었다.

내 경우에 해당 form은 '새로운 레시피 등록'과 '레시피 수정' 총 2가지 기능을한다.
하지만 위처럼 form을 지정해두면 어떤 url에서 호출됐던 naengpa:recipe_create를 호출하게된다.

그러면 하나의 form에서 2가지 기능을 호출하려면 어떻게 해야할까?

바로 action값을 넣어주지 않는 것이다.

recipe_create_form.html # 등록, 수정 form 화면

<form method="post" enctype="multipart/form-data" class="post-form">

위 코드 처럼 action값을 넣어주지 않으면 현재 페이지의 URL이 디폴트 action이 된다.

몇시간의 삽질 끝에 form에서 action값을 지우고 나니 수정기능을 온전히 사용할 수 있게 되었다.

삽질 끝에 문제를 해결하는 쾌감은~ 크

profile
신입 개발자

0개의 댓글