본문 바로가기
관리자

Programming-[Backend]/Django

Django로 Pinterest 따라 만들기-10. Profileapp 마무리, 리팩토링

728x90
반응형

 

1. ProfileUpdateView

 

ProfileUpdateView 생성

createView와 거의 동일하게 생성한다.

 

views.py 일부

class ProfileUpdateView(UpdateView):
    model = Profile
    context_object_name = 'target_profile'
    form_class = ProfileCreationForm
    success_url = reverse_lazy('accountapp:hello_world')
    template_name = 'profileapp/update.html'

update.html

enctype을 추가해주었다.

{%  extends 'base.html' %}
{% load bootstrap4 %}

{% block content %}
    <div style="text-align: center; max-width: 500px; margin: 4rem auto">
    <div class="mb-4">
        <h4>Update Profile</h4>
    </div>
        <form action="{% url 'profileapp:update' pk=target_profile.pk %}" method="post" enctype="multipart/form-data">
            {%  csrf_token %}
            {% bootstrap_form form %}
            <input type="submit" class="btn btn-dark rounded-pill col-6 mt-3">
        </form>
    </div>
{% endblock %}

 

urls.py

app_name = 'profileapp'

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

 

accoutnapp/detail.html의 일부

profile update 페이지로 이동할 수 있는 링크를 추가해준다.

{% if target_user.profile %}
<p>
    {{ target_user.profile.nickname }}
<a href="{% url 'profileapp:update' pk=target_user.profile.pk %}">
    edit
</a>
</p>

 

결과 화면

 

 

 

 

이미지 파일 표시하기

 

프로필 페이지에 이미지를 표시해본다. 부가적으로 메시지도 추가한다.

 

accoutnapp/detail.html 일부

{% if target_user.profile %}
    <img src="{{ target_user.profile.image.url }}" alt=""
         style="height: 10rem; width: 10rem; border-radius: 20rem; margin-bottom: 2rem;">
    <p>
        {{ target_user.profile.nickname }}
        <a href="{% url 'profileapp:update' pk=target_user.profile.pk %}">
            edit
        </a>
    <h6>
        {{ target_user.profile.message }}
    </h6>
    </p>

 

static url 추가

단순히 img 태그만 추가하면 이미지 파일이 보이지 않는다. 이것은 이미지 파일 등 정적 리소스 파일에 대한 라우팅을 해주지 않아서이다. prgmatic/urls.py에 +static으로 MEDIA 파일들에 대한 라우팅 설정을 추가한다.

 

urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/', include('accountapp.urls')),
    path('profiles/', include('profileapp.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

static 모듈의 위치는 django.conf.urls.static이다.

 

프로필 이미지까지 추가되었다.

 

Decorator 처리

 

profile에도 인증 정보를 검사하는 decorator를 추가한다. accountapp에서 복사해와서 약간만 변경한다. 본인의 profile만 수정할 수 있도록 하기 위해서 profile.user가 request.user와 일치하는지 검사한다.

 

profileapp/decorators.py

from django.contrib.auth.models import User
from django.http import HttpResponseForbidden

from profileapp.models import Profile


def profile_ownership_required(func):
    def decorated(request, *args, **kwargs):
        profile = Profile.objects.get(pk=kwargs['pk'])
        if not profile.user == request.user:
            return HttpResponseForbidden()
        return func(request, *args, **kwargs)
    return decorated

 

profileapp/views.py 일부

@method_decorator(profile_ownership_required, 'get')
@method_decorator(profile_ownership_required, 'post')
class ProfileUpdateView(UpdateView):
    model = Profile
    context_object_name = 'target_profile'
    form_class = ProfileCreationForm
    success_url = reverse_lazy('accountapp:hello_world')
    template_name = 'profileapp/update.html'

 

 

 

 

 


 

2. 리팩토링

 

마무리 작업으로 리팩토링을 한다.

 

success_url 수정 : 동적 redirect url 적용

일단 프로필 생성 또는 수정 후 홈페이지로 이동하도록 reverse_lazy('accoutnapp:hello_world')로 지정해놨는데, 실제로는 detail 페이지로 이동하는 것이 상식적이다. 이를 위해서 success_url을 변경해야한다.

 

그런데 detail 페이지는 profile의 pk 값을 받도록 되어있으므로 단순히 reverse_lazy로 redirect가 어렵다. 이를 위해서 get_success_url 메서드를 오버라이딩한다. 기존 각 View 아래에 있던 success_url 속성은 제거한다.

 

profileapp/views.py

class ProfileCreateView(CreateView):
    model = Profile
    context_object_name = 'target_profile'
    form_class = ProfileCreationForm
    template_name = 'profileapp/create.html'

    def form_valid(self, form):
        #생략

    def get_success_url(self):
        return reverse('accountapp:detail', kwargs={'pk': self.object.user.pk})


@method_decorator(profile_ownership_required, 'get')
@method_decorator(profile_ownership_required, 'post')
class ProfileUpdateView(UpdateView):
    #생략

    def get_success_url(self):
        return reverse('accountapp:detail', kwargs={'pk': self.object.user.pk})

 

 

 

프로필 수정 인증 처리

 

마지막으로 프로필을 변경할 수 있는 create, edit 버튼은 로그인 사용자가 프로필의 주인일때만 노출되도록 설정한다.(아래 코드에서 ### 사이 부분만)

 

accountapp/detail.html

{% if target_user.profile %}
    <img src="{{ target_user.profile.image.url }}" alt=""
         style="height: 12rem; width: 12rem; border-radius: 20rem; margin-bottom: 2rem;">
    <p>
        {{ target_user.profile.nickname }}
        ###
        {% if target_user == user %}
            <a href="{% url 'profileapp:update' pk=target_user.profile.pk %}">
                edit
            </a>
        {% endif %}
        ###
    <h5 style="margin-bottom: 3rem;">
        {{ target_user.profile.message }}
    </h5>
    </p>
{% else %}
	###
    {% if target_user == user %}
        <a href="{% url 'profileapp:create' %}">
            <h2 style="font-family: 'NanumSquareB'">
                Create Profile
            </h2>
        </a>
    {% else %}
        <h2>
            닉네임 미설정
        </h2>
    {% endif %}
    ###

{% endif %}

 

 


 

참조

1. 작정하고 장고! Django로 Pinterest 따라만들기 : 바닥부터 배포까지-박형석님 인프런 강의

https://www.inflearn.com/course/%EC%9E%A5%EA%B3%A0-%ED%95%80%ED%84%B0%EB%A0%88%EC%8A%A4%ED%8A%B8/dashboard

 

 

728x90
반응형