ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • django Update Profile by FBV
    Project using python/Cloning Airbnb 2021. 3. 5. 09:22

    url 설정

    config/urls.py

    urlpatterns = [
        path("users", include("users.urls", namespace="users")),
    ]

    users/urls.py

    from django.urls import path
    from . import views
    
    app_name = "users"
    
    urlpatterns = [path("<int:pk>/update-profile/", views.updateProfile, name="update-profile")]
    

    {% url %}

      userDetail.html의 일부다. Edit Profile button을 누르면 profile을 수정할 수 있는 page로 간다. url template tag를 이용해서 update_profile page로 갈 수 있게 한다. {% url 'users:update-profile' user.pk %}는 /users/<int:pk>/update-profile/과 같다.

    FBV(Function Based View)

    users/views.py

      FBV에서는 if 문으로 GET method 요청이 왔을 때와 POST method 요청이 왔을 때를 구분한다. GET은 page를 보여주고 POST는 client로부터 온 data를 처리한다.

    # users/views.py
    
    from django.shortcuts import render, redirect, reverse
    from django.contrib import messages
    from .exception import VerifyUser
    
    @login_required
    def updateProfile(request, pk):
        if request.method == "GET":
            try:
                if request.user.pk != pk:
                    raise VerifyUser("Page Not found")
    
                user = models.User.objects.get_or_none(pk=pk)
                if user is None:
                    messages.error(request, "User does not exist")
                    return redirect(reverse("core:home"))
                genders = models.User.GENDER_CHOICES
                languages = models.User.LANGUAGE_CHOICES
                currencies = models.User.CURRENCY_CHOICES
                login_methods = models.User.LOGIN_CHOICES
    
                choices = {
                    "genders": genders,
                    "languages": languages,
                    "currencies": currencies,
                    "login_methods": login_methods,
                }
    
                return render(
                    request,
                    "pages/users/update_profile.html",
                    context={"user": user, **choices},
                )
            except VerifyUser as error:
                messages.error(request, error)
                return redirect("core:home")
            return render(request, "pages/users/update_profile.html", {"user": user})
        elif request.method == "POST":
            try:
                if request.user.pk != pk:
                    raise VerifyUser("Page Not found")
    
                user = models.User.objects.get_or_none(pk=pk)
                if user is None:
                    messages.error(request, "User does not exist")
                    return redirect(reverse("core:home"))
    
                avatar = request.FILES.get("avatar")
                if avatar is not None and avatar != "":
                    user.avatar = avatar
    
                first_name = request.POST.get("first_name")
                if first_name is not None:
                    user.first_name = first_name
    
                last_name = request.POST.get("last_name")
                if last_name is not None:
                    user.last_name = last_name
    
                email = request.POST.get("email")
                if email is not None:
                    user.email = email
    
                gender = request.POST.get("gender")
                if gender is not None:
                    user.gender = gender
    
                language = request.POST.get("language")
                if language is not None:
                    user.language = language
    
                currency = request.POST.get("currency")
                if currency is not None:
                    user.currency = currency
    
                birthdate = request.POST.get("birthdate")
    
                if birthdate is not None:
                    user.birthdate = birthdate
    
                superhost = bool(request.POST.get("superhost"))
                if superhost is not None:
                    user.superhost = superhost
    
                bio = request.POST.get("bio")
                if bio is not None:
                    user.bio = bio
    
                user.save()
                messages.success(request, f"{user.email} profile update succeded")
                return redirect(reverse("users:profile", kwargs={"pk": pk}))
            except VerifyUser as error:
                messages.error(request, error)
                return redirect("core:home")

    templates

    pages/users/update_profile.html

      <form> tag에 enctype="multipart/form-data" attribute가 있다. django가 file을 업로드할 때 사용하는 속성이다. views.py에서는 request.FILES.get()으로 업로드하는 file에 접근할 수 있다.

      {% csrf_token %}은 csrf 공격을 막기 위한 token이다. django는 보안이 뛰어나기 때문에 {% csrf_token %} tag를 사용하지 않으면 submit이 안 된다. csrf 공격의 보안은 절대 client를 신뢰하지 않는 것으로 시작한다. 즉, 이 token 값을 가지지 않은 브라우저 요청은 받아들이지 않는다.

    {% extends 'base.html' %}
    
    
    {% block page_title %}
      Edit {{user.first_name}}'s Profile
    {% endblock page_title %}
    
    {% block search-bar %}
    <div></div>
    {% endblock search-bar %}
    
    {% block content %}
      <div class="background">
        <div class="wrap">
          <div class="flex flex-col items-center justify-center">
            <div class="mb-4">
              {% include 'mixins/avatar.html' with user=user %}
            </div>
            {% if user.login_method == "github" %}
              <div class="flex items-center mb-4">
                <h3 class="font-bold text-base mr-2">Github Email:</h3>
                <span>{{user.email}}</span>
              </div>
            {% elif user.login_method == "kakao" %}
              <div class="flex items-center mb-4">
                <h3 class="font-bold text-base mr-2">Kakao Email:</h3>
                <span>{{user.email}}</span>
              </div>
            {% endif %}
          </div>
          <form method="post" class="form" enctype="multipart/form-data">
            {% csrf_token %}
            <div class="form_input rounded-tl-lg rounded-tr-lg">
              <label for="first_name">First Name</label>
              <input type="text" id="first_name" placeholder="First Name" value="{{user.first_name}}" name="first_name">
            </div>
    
            <div class="form_input">
              <label for="last_name">Last Name</label>
              <input type="text" id="last_name" placeholder="Last Name" value="{{user.last_name}}" name="last_name">
            </div>
    
              {% if user.login_method == "email" %}
                <div class="form_input">
                  <label for="email">Email</label>
                  <input type="text" id="email" placeholder="Email" value="{{user.email}}" name="email">
                </div>
              {% endif %}
    
            {% if user.login_method == "email" %}
              <div class="form_input">
                <label for="avatar">Avatar</label>
                <input type="file" id="avatar" name="avatar" accept="image/*">
              </div>
            {% endif %}
    
            <div class="select">
              <label for="gender">Gender</label>
              <select name="gender" id="gender">
                {% for key, value in genders %}
                  <option value="{{value}}" {% if value == user.gender %}selected{% endif %}>
                    {{value}}
                  </option>
                {% endfor %}
              </select>
            </div>
    
            <div class="select">
              <label for="language">Language</label>
              <select name="language" id="language">
                {% for key, value in languages %}
                  <option value="{{value}}" {% if value == user.language %}selected{% endif %}>
                    {{value}}
                  </option>
                {% endfor %}
              </select>
            </div>
            
            <div class="select">
              <label for="currency">Currency</label>
              <select name="currency" id="currency">
                {% for key, value in currencies %}
                  <option value="{{value}}" {% if value == user.currency %}selected{% endif %}>
                    {{value}}
                  </option>
                {% endfor %}
              </select>
            </div>
    
            <div class="birthdate">
              <label for="birthdate">Birthdate</label>
              <input type="date" id="birthdate" name="birthdate" placeholder="Birthdate" value="{{user.birthdate|date:'Y-m-d'}}" required>
            </div>
    
            <div class="form_input rounded-br-lg rounded-bl-lg">
              <textarea id="bio" placeholder="Bio" name="bio">{{user.bio}}</textarea>
            </div>
            <button class="form_button">Edit Profile</button>
          </form>
          {% if user.login_method == 'email' %}
            <button class="button bg-red-500">
              <a href="#">Change Password</a>
            </button>
          {% endif %}
          <button class="button bg-gray-700">
            <a href="{% url 'users:profile' user.pk %}">Back</a>
          </button>
        </div>
      </div>
    
    {% endblock content %}
      

     

    참고 자료

    소스 코드

    github.com/zpskek/airbnb-clone-v3/commit/c3862c66c02bf1bdac912cb592768d9536584777

    'Project using python > Cloning Airbnb' 카테고리의 다른 글

    django change password by FBV  (0) 2021.03.05
    django update profile by CBV  (0) 2021.03.05
    django user profile CBV  (0) 2021.03.04
    django user profile FBV  (0) 2021.03.04
    django mailgun.com 연동(interlocking)  (0) 2021.03.04

    댓글

Designed by Tistory.