작정하고 장고 25강 - UpdateView를 이용한 비밀번호 변경 구현

IkSun·2023년 5월 4일

작정하고 장고

목록 보기
25/46

이번시간에는 UpdateView

  • UpdateView 는 CreateView 에서 들어가는 중요한 파라미터가 사실상 거의 동일 하기 때문에 CreateView 를 복사하여 UpdateView 를 수정 및 작성한다.
# pragmatic/accountapp/views.py

from django.views.generic import CreateView, DetailView, UpdateView

...

class AccountUpdateView(UpdateView):
    model = User
    context_object_name = 'target_user'
    form_class = UserCreationForm
    success_url = reverse_lazy('accountapp:hello_world')
    template_name = 'accountapp/update.html' 
  • 라우팅
# pragmatic/accountapp/urls.py

from accountapp.views import hello_world, AccountCreateView, AccountDetailView, AccountUpdateView

...

urlpatterns = [
	...
    
    path('update/<int:pk>', AccountUpdateView.as_view(), name='update'),
    
]

update.html 작성

  • pk=user.pk : update 에서는 integer 값이 pk 에 대한 정보를 update.html 에 반영해서 보내주게 된다.
  • 본인이 본인 페이지를 들어갔을 때 그 페이지 주인이 본인 개인 정보를 수정할 수 있는 링크가 있어야한다 \to detail.html 에서 그 링크를 만들어준다.
    • target_user 라는 것으로 이 페이지 주인의 user 객체를 얻는 데 따라서 if 문으로 target_user 가 지금 접속한 user 와 같은지 비교

      • 같다면 정보 수정 링크를 보여주도록 한다.
<!--pragmatic/accountapp/templates/accountapp/update.html-->
{% extends 'base.html' %}
{% load bootstrap4 %}

{% block content %}

  <div style="text-align : center; max-width: 500px; margin: 4rem auto;">>
    <div class="mb-4"> <!-- margin bottom 해서 4배 -->
      <h4>Chang Info</h4>
    </div>
    <!--url 일원화, pk=user.pk->pk=target_user.pk 으로 수정 post 방식 으로 전송 -->
    <form action="{% url 'accountapp:update' pk=target_user.pk %}" method="post">  
      {% csrf_token %}  <!-- csrf_token 은 항상 들어 가야 하는 것 -->
      {% bootstrap_form form %}
      <input type="submit" class="btn btn-dark rounded-pill col-6 mt-3">
    </form>
  </div>

{% endblock %}
<!--pragmatic/accountapp/templates/accountapp/detail.html-->
{% extends 'base.html'%}

{% block content %}

  <div>
    <div style="text-align: center; max-width: 500px; margin: 4rem auto;">
      <p>
        {{ user.date_joined }}
      </p>
      <h2 style="font-family: 'NanumSquareB'">
        {{ user.username }}
      </h2>
		
      <!-- 추가한 부분 -->
      {% if target_user == user %}
      <a href="{% url 'accountapp:update' pk=user.pk%}">
        <p>
          Change Info
        </p>
      </a>
      {% endif %}
    </div>
  </div>

{% endblock %}
  • Change Info 링크가 생성되었다

  • 링크 클릭시 계정 생성 페이지가 나왔다

    • 정보를 수정하고 다시 로그인을 하면 정상적으로 정보가 변경됨을 확인할 수있다.

문제점

  • 위의 이미지에서 볼 수 있듯이 정보 수정 페이지로 가게 되면 username 이 활성화 되어있다. 즉 ID 와 PW 를 동시에 변경할 수 있기 때문에 서버 입장에서는 좋은 시스템은 아님.
    • 정보 수정 페이지로 갔을때 username 칸을 수정하지 못하게 비활성화하는 기능을 추가하여 해결한다.
  • accountapp 에 forms 라는 py 파일을 만든다.
  • 이전에 views.py 에서 AccountUpdateView 를 작성할 때, AccountCreateView 와 마찬가지로form_class = UserCreationForm 을 사용했었는데, 이 form 을 상속 받아서 약간의 customize 를 할 것이다.
    • UserCreationForm 를 상속받아 AccountUpdateForm 클래스를 다음과 같이 커스터마이즈
    • 혹시나 이 칸을 나중에 브라우저 쪽에서 원치 않는 조작으로 서버의 변경된 값을 보냈다고 할지라도 disabled 가 True 로 설정된 이상 서버에 반영되지 않는다.
    • 최종적으로 views.py 단에서 form_class 를 우리가 커스터마이즈 한 AccountUpdateForm 로 수정
    • 다음과 같이 ID 부분의 수정이 비활성화 되었음을 확인할 수 있다.
# pragmatic/accountapp/forms.py

from django.contrib.auth.forms import UserCreationForm

class AccountUpdateForm(UserCreationForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.fields['username'].disabled = True
        # 필드로 가지고 있는 값들 중에 username 을 disabled 라는 속성을 활성화
        # 만약 바로 위 self.fields 코드가 없다면
        # 우리가 import 한 UserCreationForm 과 그걸 상속받은 AccountUpdateForm은 똑겉은 form 이 됨
        # 이 한줄이 추가 됨 으로써 초기화 이후에 username 의 칸을 비활성화 시켜줌
# pragmatic/accountapp/views.py

from accountapp.forms import AccountUpdateForm
...
class AccountUpdateView(UpdateView):
    model = User
    form_class = AccountUpdateForm #UserCreationForm
    success_url = reverse_lazy('accountapp:hello_world')
    template_name = 'accountapp/update.html'

브라우저 창에서의 조작

  • 다음과 같이 브라우저 상에서 ID 부분을 조작한다고 하더라도 PW 를 입력하고 제출을 누르면 ID 부분은 바뀌지 않고 비밀번호만 바뀌는 것을 확인할 수 있다.

commit

profile
공부한 것 기록용

0개의 댓글