Django - UpdateView pk 있을때 없을때 다 처리하기

Django - UpdateView pk 있을때 없을때 다 처리하기
Photo by Sangga Rima Roman Selia / Unsplash

UpdateView pk 없이 사용하는 방법을 전 포스트에서 알아 봤는데 PK 값이 url에 있든 없든 하나의 View로 다 처리하고 싶어졌다.

일반 사용자는 자기꺼만 처리하면 되지만, superuser 혹은 admin은 다른 사용자 정보를 수정하고 싶을 수 도 있기 때문에 pk 값을 넘겨 받아서 사용하는 것도 같은 UpdateView에서 처리하고 싶었다.

그냥 get_object() 함수 내에서 pk 유무를 보고 처리하면 안되나......된다! 코드를 올려둔다.



@method_decorator(login_required, name="dispatch")
class profile_update_view(UpdateView):
    model = Profile
    # fields = "__all__"
    fields = ["phone"]
    template_name = "profile.html"

    def get_object(self):
        print("profile_update_view get_object()", self.request.user, self.kwargs.get("pk"))
        if self.kwargs.get("pk"):
            if self.request.user.is_superuser:
                return Profile.objects.get(user=self.kwargs.get("pk"))
            else:
                set_page_message(self.request, messages.INFO, f"접근 권한이 없습니다!")
        return Profile.objects.get(user=self.request.user)
        # return self.request.user

    def get_success_url(self):
        return self.request.META["HTTP_REFERER"]

self.kwargs.get("pk") 로 pk 값이 url을 통해 넘어오는지 유무를 알수 있고 그 상황에 맞게 각자 원하는 코드를 집어 넣으면 될듯!

단!!!!  urls.py 함수에서 pk 가 있는 것, 없는 것 다 같은 view를 호출하도록 꼭 해줘야 한다.

    path("profile", profile_update_view.as_view(), name="profile_list_1"),
    path("profile/<int:pk>", profile_update_view.as_view(), name="profile_list"),

참고 사이트

아래 글은 한번 정독을 권고!!

Deep Dive into Class-Based Views — Python 401 2.1 documentation

장고 소스도 읽어보자. 오버라이딩 하려면 먼가 알아야징

slug_url_kwarg, pk_url_kwarg 를 보면 왜 'pk' 'slug' 라는 키워드를 그냥 써도 되는지 알 수 있다. 여기에 적힌 문자열을 인식하는 것 뿐이다 😊

# django/views/generic/detail.py

class SingleObjectMixin(ContextMixin):
    """
    Provides the ability to retrieve a single object for further manipulation.
    """
    model = None
    queryset = None
    slug_field = 'slug'
    context_object_name = None
    slug_url_kwarg = 'slug'
    pk_url_kwarg = 'pk'
    query_pk_and_slug = False

    def get_object(self, queryset=None):
        """
        Returns the object the view is displaying.

        By default this requires `self.queryset` and a `pk` or `slug` argument
        in the URLconf, but subclasses can override this to return any object.
        """
        # Use a custom queryset if provided; this is required for subclasses
        # like DateDetailView
        if queryset is None:
            queryset = self.get_queryset()

        # Next, try looking up by primary key.
        pk = self.kwargs.get(self.pk_url_kwarg, None)
        slug = self.kwargs.get(self.slug_url_kwarg, None)
        if pk is not None:
            queryset = queryset.filter(pk=pk)

        # Next, try looking up by slug.
        if slug is not None and (pk is None or self.query_pk_and_slug):
            slug_field = self.get_slug_field()
            queryset = queryset.filter(**{slug_field: slug})

        # If none of those are defined, it's an error.
        if pk is None and slug is None:
            raise AttributeError("Generic detail view %s must be called with "
                                 "either an object pk or a slug."
                                 % self.__class__.__name__)

        try:
            # Get the single item from the filtered queryset
            obj = queryset.get()
        except queryset.model.DoesNotExist:
            raise Http404(_("No %(verbose_name)s found matching the query") %
                          {'verbose_name': queryset.model._meta.verbose_name})
        return obj